~bratsche/vlc/vlc-notify-add-actions-with-server-support

« back to all changes in this revision

Viewing changes to extras/faad2/plugins/in_mp4/in_mp4.c

  • Committer: Bazaar Package Importer
  • Date: 2008-11-28 09:29:51 UTC
  • Revision ID: jamesw@ubuntu.com-20081128092951-0y5ojboptscru17f
Tags: upstream-ubuntu-0.8.6.release.e+x264svn20071224+faad2.6.1
ImportĀ upstreamĀ versionĀ 0.8.6.release.e+x264svn20071224+faad2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3
 
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
4
 
**  
5
 
** This program is free software; you can redistribute it and/or modify
6
 
** it under the terms of the GNU General Public License as published by
7
 
** the Free Software Foundation; either version 2 of the License, or
8
 
** (at your option) any later version.
9
 
** 
10
 
** This program is distributed in the hope that it will be useful,
11
 
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
** GNU General Public License for more details.
14
 
** 
15
 
** You should have received a copy of the GNU General Public License
16
 
** along with this program; if not, write to the Free Software 
17
 
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
**
19
 
** Any non-GPL usage of this software or parts of this software is strictly
20
 
** forbidden.
21
 
**
22
 
** Commercial non-GPL licensing of this software is possible.
23
 
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
24
 
**
25
 
** $Id: in_mp4.c,v 1.56 2004/10/19 18:02:10 menno Exp $
26
 
**/
27
 
 
28
 
//#define DEBUG_OUTPUT
29
 
 
30
 
#define WIN32_LEAN_AND_MEAN
31
 
#include <windows.h>
32
 
#include <commctrl.h>
33
 
#include <commdlg.h>
34
 
#include <stdlib.h>
35
 
#include <stdio.h>
36
 
#include <io.h>
37
 
#include <math.h>
38
 
#include <neaacdec.h>
39
 
#define USE_TAGGING
40
 
#include <mp4ff.h>
41
 
 
42
 
#include "resource.h"
43
 
#include "in2.h"
44
 
#include "utils.h"
45
 
#include "config.h"
46
 
#include "aacinfo.h"
47
 
 
48
 
const char *long_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0AAC\0AAC Files (*.AAC)\0";
49
 
const char *short_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0";
50
 
 
51
 
static long priority_table[] = {
52
 
    0,
53
 
    THREAD_PRIORITY_HIGHEST,
54
 
    THREAD_PRIORITY_ABOVE_NORMAL,
55
 
    THREAD_PRIORITY_NORMAL,
56
 
    THREAD_PRIORITY_BELOW_NORMAL,
57
 
    THREAD_PRIORITY_LOWEST
58
 
};
59
 
static int res_id_table[] = {
60
 
    IDC_16BITS,
61
 
    IDC_24BITS,
62
 
    IDC_32BITS,
63
 
    0,
64
 
    0,
65
 
    /*IDC_16BITS_DITHERED*/ IDC_16BITS /* temp hack */
66
 
};
67
 
static int res_table[] = {
68
 
    16,
69
 
    24,
70
 
    32,
71
 
    0,
72
 
    0,
73
 
    16
74
 
};
75
 
static char info_fn[_MAX_PATH];
76
 
 
77
 
// post this to the main window at end of file (after playback has stopped)
78
 
#define WM_WA_AAC_EOF WM_USER+2
79
 
 
80
 
struct seek_list
81
 
{
82
 
    struct seek_list *next;
83
 
    __int64 offset;
84
 
};
85
 
 
86
 
typedef struct state
87
 
{
88
 
    /* general stuff */
89
 
    NeAACDecHandle hDecoder;
90
 
    int samplerate;
91
 
    unsigned char channels;
92
 
    double decode_pos_ms; // current decoding position, in milliseconds
93
 
    int paused; // are we paused?
94
 
    int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
95
 
    char filename[_MAX_PATH];
96
 
    int filetype; /* 0: MP4; 1: AAC */
97
 
    int last_frame;
98
 
    __int64 last_offset;
99
 
 
100
 
    /* MP4 stuff */
101
 
    mp4ff_t *mp4file;
102
 
    int mp4track;
103
 
    long numSamples;
104
 
    long sampleId;
105
 
    mp4ff_callback_t mp4cb;
106
 
    FILE *mp4File;
107
 
 
108
 
    /* AAC stuff */
109
 
    FILE *aacfile;
110
 
    long m_aac_bytes_into_buffer;
111
 
    long m_aac_bytes_consumed;
112
 
    __int64 m_file_offset;
113
 
    unsigned char *m_aac_buffer;
114
 
    int m_at_eof;
115
 
    double cur_pos_sec;
116
 
    int m_header_type;
117
 
    struct seek_list *m_head;
118
 
    struct seek_list *m_tail;
119
 
    unsigned long m_length;
120
 
 
121
 
    /* for gapless decoding */
122
 
    unsigned int useAacLength;
123
 
    unsigned int framesize;
124
 
    unsigned int initial;
125
 
    unsigned long timescale;
126
 
} state;
127
 
 
128
 
static state mp4state;
129
 
 
130
 
static In_Module module; // the output module (declared near the bottom of this file)
131
 
 
132
 
static int killPlayThread;
133
 
static int PlayThreadAlive = 0; // 1=play thread still running
134
 
HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
135
 
 
136
 
/* Function definitions */
137
 
void *decode_aac_frame(state *st, NeAACDecFrameInfo *frameInfo);
138
 
DWORD WINAPI MP4PlayThread(void *b); // the decode thread procedure
139
 
DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure
140
 
 
141
 
 
142
 
uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
143
 
{
144
 
    return fread(buffer, 1, length, (FILE*)user_data);
145
 
}
146
 
 
147
 
uint32_t seek_callback(void *user_data, uint64_t position)
148
 
{
149
 
    return fseek((FILE*)user_data, position, SEEK_SET);
150
 
}
151
 
 
152
 
uint32_t write_callback(void *user_data, void *buffer, uint32_t length)
153
 
{
154
 
    return fwrite(buffer, 1, length, (FILE*)user_data);
155
 
}
156
 
 
157
 
uint32_t truncate_callback(void *user_data)
158
 
{
159
 
    _chsize(fileno((FILE*)user_data), ftell((FILE*)user_data));
160
 
    return 1;
161
 
}
162
 
 
163
 
 
164
 
int tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
165
 
{
166
 
    void *backup = (void *)tags->tags;
167
 
 
168
 
    if (!item || (item && !*item) || !value) return 0;
169
 
 
170
 
    tags->tags = (mp4ff_tag_t *)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
171
 
    if (!tags->tags) {
172
 
        if (backup) free(backup);
173
 
        return 0;
174
 
    }
175
 
    else
176
 
    {
177
 
        size_t i_len = strlen(item);
178
 
        if (v_len == 0) v_len = strlen(value);
179
 
 
180
 
        tags->tags[tags->count].item = (char *)malloc(i_len+1);
181
 
        tags->tags[tags->count].value = (char *)malloc(v_len+1);
182
 
 
183
 
        if (!tags->tags[tags->count].item || !tags->tags[tags->count].value)
184
 
        {
185
 
            if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item);
186
 
            if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value);
187
 
            tags->tags[tags->count].item = NULL;
188
 
            tags->tags[tags->count].value = NULL;
189
 
            return 0;
190
 
        }
191
 
 
192
 
        memcpy(tags->tags[tags->count].item, item, i_len);
193
 
        memcpy(tags->tags[tags->count].value, value, v_len);
194
 
        tags->tags[tags->count].item[i_len] = '\0';
195
 
        tags->tags[tags->count].value[v_len] = '\0';
196
 
//        tags->tags[tags->count].len = v_len;
197
 
 
198
 
        tags->count++;
199
 
        return 1;
200
 
    }
201
 
}
202
 
 
203
 
int tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
204
 
{
205
 
    unsigned int i;
206
 
 
207
 
    if (!item || (item && !*item) || !value) return 0;
208
 
 
209
 
    for (i = 0; i < tags->count; i++)
210
 
    {
211
 
        if (!stricmp(tags->tags[i].item, item))
212
 
        {
213
 
            void *backup = (void *)tags->tags[i].value;
214
 
            if (v_len == 0) v_len = strlen(value);
215
 
 
216
 
            tags->tags[i].value = (char *)realloc(tags->tags[i].value, v_len+1);
217
 
            if (!tags->tags[i].value)
218
 
            {
219
 
                if (backup) free(backup);
220
 
                return 0;
221
 
            }
222
 
 
223
 
            memcpy(tags->tags[i].value, value, v_len);
224
 
            tags->tags[i].value[v_len] = '\0';
225
 
//            tags->tags[i].len = v_len;
226
 
 
227
 
            return 1;
228
 
        }
229
 
    }
230
 
 
231
 
    return tag_add_field(tags, item, value, v_len);
232
 
}
233
 
 
234
 
int tag_delete(mp4ff_metadata_t *tags)
235
 
{
236
 
    unsigned int i;
237
 
 
238
 
    for (i = 0; i < tags->count; i++)
239
 
    {
240
 
        if (tags->tags[i].item) free(tags->tags[i].item);
241
 
        if (tags->tags[i].value) free(tags->tags[i].value);
242
 
    }
243
 
 
244
 
    if (tags->tags) free(tags->tags);
245
 
 
246
 
    tags->tags = NULL;
247
 
    tags->count = 0;
248
 
}
249
 
 
250
 
int ReadMP4Tag(mp4ff_t *file, mp4ff_metadata_t *tags)
251
 
{
252
 
    unsigned __int8 *pValue;
253
 
    char *pName;
254
 
    unsigned int i = 0;
255
 
 
256
 
    do {
257
 
        pName = 0;
258
 
        pValue = 0;
259
 
 
260
 
 
261
 
        if (mp4ff_meta_get_by_index(file, i, (char **)&pName, &pValue))
262
 
        {
263
 
            char *val = (char *)strdup(pValue);
264
 
            if (!val) return 0;
265
 
 
266
 
            if (pName[0] == 'ļæ½')
267
 
            {
268
 
                if (memcmp(pName, "ļæ½nam", 4) == 0)
269
 
                {
270
 
                    tag_add_field(tags, "title", val, strlen(val));
271
 
                } else if (memcmp(pName, "ļæ½ART", 4) == 0) {
272
 
                    tag_add_field(tags, "artist", val, strlen(val));
273
 
                } else if (memcmp(pName, "ļæ½wrt", 4) == 0) {
274
 
                    tag_add_field(tags, "writer", val, strlen(val));
275
 
                } else if (memcmp(pName, "ļæ½alb", 4) == 0) {
276
 
                    tag_add_field(tags, "album", val, strlen(val));
277
 
                } else if (memcmp(pName, "ļæ½day", 4) == 0) {
278
 
                    tag_add_field(tags, "date", val, strlen(val));
279
 
                } else if (memcmp(pName, "ļæ½too", 4) == 0) {
280
 
                    tag_add_field(tags, "tool", val, strlen(val));
281
 
                } else if (memcmp(pName, "ļæ½cmt", 4) == 0) {
282
 
                    tag_add_field(tags, "comment", val, strlen(val));
283
 
                } else if (memcmp(pName, "ļæ½gen", 4) == 0) {
284
 
                    tag_add_field(tags, "genre", val, strlen(val));
285
 
                } else {
286
 
                    tag_add_field(tags, pName, val, strlen(val));
287
 
                }
288
 
            } else if (memcmp(pName, "covr", 4) == 0) {
289
 
                tag_add_field(tags, "cover", val, strlen(val));
290
 
            } else if (memcmp(pName, "gnre", 4) == 0) {
291
 
                tag_add_field(tags, "genre", val, strlen(val));
292
 
            } else if (memcmp(pName, "trkn", 4) == 0) {
293
 
                tag_add_field(tags, "tracknumber", val, strlen(val));
294
 
            } else if (memcmp(pName, "disk", 4) == 0) {
295
 
                tag_add_field(tags, "disc", val, strlen(val));
296
 
            } else if (memcmp(pName, "cpil", 4) == 0) {
297
 
                tag_add_field(tags, "compilation", val, strlen(val));
298
 
            } else if (memcmp(pName, "tmpo", 4) == 0) {
299
 
                tag_add_field(tags, "tempo", val, strlen(val));
300
 
            } else if (memcmp(pName, "NDFL", 4) == 0) {
301
 
                /* Removed */
302
 
            } else {
303
 
                tag_add_field(tags, pName, val, strlen(val));
304
 
            }
305
 
 
306
 
            free(val);
307
 
        }
308
 
 
309
 
        i++;
310
 
    } while (pValue != NULL);
311
 
 
312
 
    return 1;
313
 
}
314
 
 
315
 
 
316
 
#ifdef DEBUG_OUTPUT
317
 
void in_mp4_DebugOutput(char *message)
318
 
{
319
 
    char s[1024];
320
 
 
321
 
    sprintf(s, "in_mp4: %s", message);
322
 
    OutputDebugString(s);
323
 
}
324
 
#endif
325
 
 
326
 
int file_length(FILE *f)
327
 
{
328
 
    long end = 0;
329
 
    long cur = ftell(f);
330
 
    fseek(f, 0, SEEK_END);
331
 
    end = ftell(f);
332
 
    fseek(f, cur, SEEK_SET);
333
 
 
334
 
    return end;
335
 
}
336
 
 
337
 
static void show_error(HWND hwnd, char *message, ...)
338
 
{
339
 
    if (m_show_errors)
340
 
        MessageBox(hwnd, message, "Error", MB_OK);
341
 
}
342
 
 
343
 
static void config_init()
344
 
{
345
 
    char *p=INI_FILE;
346
 
    GetModuleFileName(NULL,INI_FILE,_MAX_PATH);
347
 
    while (*p) p++;
348
 
    while (p >= INI_FILE && *p != '.') p--;
349
 
    strcpy(p+1,"ini");
350
 
}
351
 
 
352
 
void config_read()
353
 
{
354
 
    char priority[10];
355
 
    char resolution[10];
356
 
    char show_errors[10];
357
 
    char use_for_aac[10];
358
 
    char downmix[10];
359
 
    char vbr_display[10];
360
 
 
361
 
    config_init();
362
 
 
363
 
    strcpy(show_errors, "1");
364
 
    strcpy(priority, "3");
365
 
    strcpy(resolution, "0");
366
 
    strcpy(use_for_aac, "1");
367
 
    strcpy(downmix, "0");
368
 
    strcpy(vbr_display, "1");
369
 
    strcpy(titleformat, "%7");
370
 
 
371
 
    RS(priority);
372
 
    RS(resolution);
373
 
    RS(show_errors);
374
 
    RS(use_for_aac);
375
 
    RS(downmix);
376
 
    RS(vbr_display);
377
 
    RS(titleformat);
378
 
 
379
 
    m_priority = atoi(priority);
380
 
    m_resolution = atoi(resolution);
381
 
    m_show_errors = atoi(show_errors);
382
 
    m_use_for_aac = atoi(use_for_aac);
383
 
    m_downmix = atoi(downmix);
384
 
    m_vbr_display = atoi(vbr_display);
385
 
}
386
 
 
387
 
void config_write()
388
 
{
389
 
    char priority[10];
390
 
    char resolution[10];
391
 
    char show_errors[10];
392
 
    char use_for_aac[10];
393
 
    char downmix[10];
394
 
    char vbr_display[10];
395
 
 
396
 
    itoa(m_priority, priority, 10);
397
 
    itoa(m_resolution, resolution, 10);
398
 
    itoa(m_show_errors, show_errors, 10);
399
 
    itoa(m_use_for_aac, use_for_aac, 10);
400
 
    itoa(m_downmix, downmix, 10);
401
 
    itoa(m_vbr_display, vbr_display, 10);
402
 
 
403
 
    WS(priority);
404
 
    WS(resolution);
405
 
    WS(show_errors);
406
 
    WS(use_for_aac);
407
 
    WS(downmix);
408
 
    WS(vbr_display);
409
 
    WS(titleformat);
410
 
}
411
 
 
412
 
void init()
413
 
{
414
 
    config_read();
415
 
}
416
 
 
417
 
void quit()
418
 
{
419
 
}
420
 
 
421
 
/* Convert UNICODE to UTF-8
422
 
   Return number of bytes written */
423
 
int unicodeToUtf8 ( const WCHAR* lpWideCharStr, char* lpMultiByteStr, int cwcChars )
424
 
{
425
 
    const unsigned short*   pwc = (unsigned short *)lpWideCharStr;
426
 
    unsigned char*          pmb = (unsigned char  *)lpMultiByteStr;
427
 
    const unsigned short*   pwce;
428
 
    size_t  cBytes = 0;
429
 
 
430
 
    if ( cwcChars >= 0 ) {
431
 
        pwce = pwc + cwcChars;
432
 
    } else {
433
 
        pwce = (unsigned short *)((size_t)-1);
434
 
    }
435
 
 
436
 
    while ( pwc < pwce ) {
437
 
        unsigned short  wc = *pwc++;
438
 
 
439
 
        if ( wc < 0x00000080 ) {
440
 
            *pmb++ = (char)wc;
441
 
            cBytes++;
442
 
        } else
443
 
        if ( wc < 0x00000800 ) {
444
 
            *pmb++ = (char)(0xC0 | ((wc >>  6) & 0x1F));
445
 
            cBytes++;
446
 
            *pmb++ = (char)(0x80 |  (wc        & 0x3F));
447
 
            cBytes++;
448
 
        } else
449
 
        if ( wc < 0x00010000 ) {
450
 
            *pmb++ = (char)(0xE0 | ((wc >> 12) & 0x0F));
451
 
            cBytes++;
452
 
            *pmb++ = (char)(0x80 | ((wc >>  6) & 0x3F));
453
 
            cBytes++;
454
 
            *pmb++ = (char)(0x80 |  (wc        & 0x3F));
455
 
            cBytes++;
456
 
        }
457
 
        if ( wc == L'\0' )
458
 
            return cBytes;
459
 
    }
460
 
 
461
 
    return cBytes;
462
 
}
463
 
 
464
 
/* Convert UTF-8 coded string to UNICODE
465
 
   Return number of characters converted */
466
 
int utf8ToUnicode ( const char* lpMultiByteStr, WCHAR* lpWideCharStr, int cmbChars )
467
 
{
468
 
    const unsigned char*    pmb = (unsigned char  *)lpMultiByteStr;
469
 
    unsigned short*         pwc = (unsigned short *)lpWideCharStr;
470
 
    const unsigned char*    pmbe;
471
 
    size_t  cwChars = 0;
472
 
 
473
 
    if ( cmbChars >= 0 ) {
474
 
        pmbe = pmb + cmbChars;
475
 
    } else {
476
 
        pmbe = (unsigned char *)((size_t)-1);
477
 
    }
478
 
 
479
 
    while ( pmb < pmbe ) {
480
 
        char            mb = *pmb++;
481
 
        unsigned int    cc = 0;
482
 
        unsigned int    wc;
483
 
 
484
 
        while ( (cc < 7) && (mb & (1 << (7 - cc)))) {
485
 
            cc++;
486
 
        }
487
 
 
488
 
        if ( cc == 1 || cc > 6 )                    // illegal character combination for UTF-8
489
 
            continue;
490
 
 
491
 
        if ( cc == 0 ) {
492
 
            wc = mb;
493
 
        } else {
494
 
            wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6);
495
 
            while ( --cc > 0 ) {
496
 
                if ( pmb == pmbe )                  // reached end of the buffer
497
 
                    return cwChars;
498
 
                mb = *pmb++;
499
 
                if ( ((mb >> 6) & 0x03) != 2 )      // not part of multibyte character
500
 
                    return cwChars;
501
 
                wc |= (mb & 0x3F) << ((cc - 1) * 6);
502
 
            }
503
 
        }
504
 
 
505
 
        if ( wc & 0xFFFF0000 )
506
 
            wc = L'?';
507
 
        *pwc++ = wc;
508
 
        cwChars++;
509
 
        if ( wc == L'\0' )
510
 
            return cwChars;
511
 
    }
512
 
 
513
 
    return cwChars;
514
 
}
515
 
 
516
 
/* convert Windows ANSI to UTF-8 */
517
 
int ConvertANSIToUTF8 ( const char* ansi, char* utf8 )
518
 
{
519
 
    WCHAR*  wszValue;          // Unicode value
520
 
    size_t  ansi_len;
521
 
    size_t  len;
522
 
 
523
 
    *utf8 = '\0';
524
 
    if ( ansi == NULL )
525
 
        return 0;
526
 
 
527
 
    ansi_len = strlen ( ansi );
528
 
 
529
 
    if ( (wszValue = (WCHAR *)malloc ( (ansi_len + 1) * 2 )) == NULL )
530
 
        return 0;
531
 
 
532
 
    /* Convert ANSI value to Unicode */
533
 
    if ( (len = MultiByteToWideChar ( CP_ACP, 0, ansi, ansi_len + 1, wszValue, (ansi_len + 1) * 2 )) == 0 ) {
534
 
        free ( wszValue );
535
 
        return 0;
536
 
    }
537
 
 
538
 
    /* Convert Unicode value to UTF-8 */
539
 
    if ( (len = unicodeToUtf8 ( wszValue, utf8, -1 )) == 0 ) {
540
 
        free ( wszValue );
541
 
        return 0;
542
 
    }
543
 
 
544
 
    free ( wszValue );
545
 
 
546
 
    return len-1;
547
 
}
548
 
 
549
 
/* convert UTF-8 to Windows ANSI */
550
 
int ConvertUTF8ToANSI ( const char* utf8, char* ansi )
551
 
{
552
 
    WCHAR*  wszValue;          // Unicode value
553
 
    size_t  utf8_len;
554
 
    size_t  len;
555
 
 
556
 
    *ansi = '\0';
557
 
    if ( utf8 == NULL )
558
 
        return 0;
559
 
 
560
 
    utf8_len = strlen ( utf8 );
561
 
 
562
 
    if ( (wszValue = (WCHAR *)malloc ( (utf8_len + 1) * 2 )) == NULL )
563
 
        return 0;
564
 
 
565
 
    /* Convert UTF-8 value to Unicode */
566
 
    if ( (len = utf8ToUnicode ( utf8, wszValue, utf8_len + 1 )) == 0 ) {
567
 
        free ( wszValue );
568
 
        return 0;
569
 
    }
570
 
 
571
 
    /* Convert Unicode value to ANSI */
572
 
    if ( (len = WideCharToMultiByte ( CP_ACP, 0, wszValue, -1, ansi, (utf8_len + 1) * 2, NULL, NULL )) == 0 ) {
573
 
        free ( wszValue );
574
 
        return 0;
575
 
    }
576
 
 
577
 
    free ( wszValue );
578
 
 
579
 
    return len-1;
580
 
}
581
 
 
582
 
BOOL uSetDlgItemText(HWND hwnd, int id, const char *str)
583
 
{
584
 
    char *temp;
585
 
    size_t len;
586
 
    int r;
587
 
 
588
 
    if (!str) return FALSE;
589
 
    if (!*str) return TRUE;
590
 
    len = strlen(str);
591
 
    temp = malloc(len+1);
592
 
    if (!temp) return FALSE;
593
 
    r = ConvertUTF8ToANSI(str, temp);
594
 
    if (r > 0)
595
 
        SetDlgItemText(hwnd, id, temp);
596
 
    free(temp);
597
 
 
598
 
    return r>0 ? TRUE : FALSE;
599
 
}
600
 
 
601
 
UINT uGetDlgItemText(HWND hwnd, int id, char *str, int max)
602
 
{
603
 
    char *temp, *utf8;
604
 
    int len;
605
 
    HWND w;
606
 
 
607
 
    if (!str || !max) return 0;
608
 
    *str = '\0';
609
 
    w = GetDlgItem(hwnd, id);
610
 
    len = GetWindowTextLength(w);
611
 
    temp = malloc(len+1);
612
 
    if (!temp) return 0;
613
 
    utf8 = malloc((len+1)*4);
614
 
    if (!utf8)
615
 
    {
616
 
        free(temp);
617
 
        return 0;
618
 
    }
619
 
 
620
 
    len = GetWindowText(w, temp, len+1);
621
 
    if (len > 0)
622
 
    {
623
 
        len = ConvertANSIToUTF8(temp, utf8);
624
 
        if (len > max-1)
625
 
        {
626
 
            len = max-1;
627
 
            utf8[max] = '\0';
628
 
        }
629
 
        memcpy(str, utf8, len+1);
630
 
    }
631
 
 
632
 
    free(temp);
633
 
    free(utf8);
634
 
 
635
 
    return len;
636
 
}
637
 
 
638
 
static void mp4fileinfo(mp4ff_t *mp4, char *info, size_t len)
639
 
{
640
 
    char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
641
 
    long samples;
642
 
    float f = 1024.0;
643
 
    float seconds;
644
 
    int track;
645
 
 
646
 
    NeAACDecHandle hDecoder;
647
 
    NeAACDecFrameInfo frameInfo;
648
 
    mp4AudioSpecificConfig mp4ASC = {0};
649
 
    unsigned char *buffer = NULL;
650
 
    int buffer_size = 0;
651
 
    unsigned long sr = 0;
652
 
    unsigned char ch = 0;
653
 
 
654
 
    if ((track = GetAACTrack(mp4)) < 0)
655
 
    {
656
 
        info[0] = '\0';
657
 
        return;
658
 
    }
659
 
 
660
 
    hDecoder = NeAACDecOpen();
661
 
 
662
 
    samples = mp4ff_num_samples(mp4, track);
663
 
 
664
 
    mp4ff_get_decoder_config(mp4, track, &buffer, &buffer_size);
665
 
    if (buffer)
666
 
    {
667
 
        if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
668
 
        {
669
 
            if (mp4ASC.frameLengthFlag == 1) f = 960.0;
670
 
            if (mp4ASC.sbr_present_flag == 1) f *= 2;
671
 
        }
672
 
 
673
 
        if(NeAACDecInit2(hDecoder, buffer, buffer_size, &sr, &ch) < 0)
674
 
        {
675
 
            /* If some error initializing occured, skip the file */
676
 
            free(buffer);
677
 
            return;
678
 
        }
679
 
 
680
 
        free(buffer);
681
 
        buffer = NULL;
682
 
    }
683
 
 
684
 
    if (mp4ff_read_sample(mp4, track, 0, &buffer,  &buffer_size) == 0)
685
 
    {
686
 
        return;
687
 
    }
688
 
    NeAACDecDecode(hDecoder, &frameInfo, buffer, buffer_size);
689
 
 
690
 
    if (buffer) free(buffer);
691
 
 
692
 
    seconds = (float)samples*(float)(f-1.0)/(float)mp4ASC.samplingFrequency;
693
 
 
694
 
    wsprintf(info, "MPEG-4 %s, %d.%d secs, %d ch, %d Hz\nSBR: %s\nParametric stereo: %s",
695
 
        ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
696
 
        (int)(seconds),
697
 
        (int)(seconds*1000.0 + 0.5) % 1000,
698
 
        mp4ASC.channelsConfiguration,
699
 
        mp4ASC.samplingFrequency,
700
 
        /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
701
 
        (frameInfo.sbr == 0) ? "off" : ((frameInfo.sbr == 1) ? "on, normal" : ((frameInfo.sbr == 2) ? "on, downsampled" : "off, upsampled")),
702
 
        (frameInfo.ps == 0) ? "no" : "yes");
703
 
 
704
 
    NeAACDecClose(hDecoder);
705
 
}
706
 
 
707
 
BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
708
 
                                   WPARAM wParam, LPARAM lParam)
709
 
{
710
 
    char file_info[1024];
711
 
    mp4ff_t *file;
712
 
    FILE *mp4File;
713
 
    mp4ff_callback_t mp4cb = {0};
714
 
    char *pVal;
715
 
    mp4ff_metadata_t tags;
716
 
    char dummy1[1024];
717
 
    char temp[1024];
718
 
    int dummy, dummy2, dummy3;
719
 
    tags.count = 0;
720
 
    tags.tags = NULL;
721
 
 
722
 
#ifdef DEBUG_OUTPUT
723
 
    in_mp4_DebugOutput("mp4_info_dialog_proc");
724
 
#endif
725
 
 
726
 
    switch (message) {
727
 
    case WM_INITDIALOG:
728
 
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT), FALSE);
729
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT), SW_HIDE);
730
 
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), FALSE);
731
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), SW_HIDE);
732
 
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), FALSE);
733
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), SW_HIDE);
734
 
 
735
 
        mp4File = fopen(info_fn, "rb");
736
 
        mp4cb.read = read_callback;
737
 
        mp4cb.seek = seek_callback;
738
 
        mp4cb.user_data = mp4File;
739
 
 
740
 
 
741
 
        file = mp4ff_open_read(&mp4cb);
742
 
        if (file == NULL)
743
 
            return FALSE;
744
 
 
745
 
        mp4fileinfo(file, file_info, 1024);
746
 
        SetDlgItemText(hwndDlg, IDC_INFOTEXT, file_info);
747
 
 
748
 
        /* get Metadata */
749
 
 
750
 
        pVal = NULL;
751
 
        if (mp4ff_meta_get_title(file, &pVal))
752
 
            uSetDlgItemText(hwndDlg,IDC_METANAME, pVal);
753
 
 
754
 
        pVal = NULL;
755
 
        if (mp4ff_meta_get_artist(file, &pVal))
756
 
            uSetDlgItemText(hwndDlg,IDC_METAARTIST, pVal);
757
 
 
758
 
        pVal = NULL;
759
 
        if (mp4ff_meta_get_writer(file, &pVal))
760
 
            uSetDlgItemText(hwndDlg,IDC_METAWRITER, pVal);
761
 
 
762
 
        pVal = NULL;
763
 
        if (mp4ff_meta_get_comment(file, &pVal))
764
 
            uSetDlgItemText(hwndDlg,IDC_METACOMMENTS, pVal);
765
 
 
766
 
        pVal = NULL;
767
 
        if (mp4ff_meta_get_album(file, &pVal))
768
 
            uSetDlgItemText(hwndDlg,IDC_METAALBUM, pVal);
769
 
 
770
 
        pVal = NULL;
771
 
        if (mp4ff_meta_get_genre(file, &pVal))
772
 
            uSetDlgItemText(hwndDlg,IDC_METAGENRE, pVal);
773
 
 
774
 
        pVal = NULL;
775
 
        if (mp4ff_meta_get_track(file, &pVal))
776
 
        {
777
 
            SetDlgItemText(hwndDlg,IDC_METATRACK1, pVal);
778
 
 
779
 
            //pVal = NULL;
780
 
            //mp4ff_meta_get_totaltracks(file, &pVal);
781
 
            //SetDlgItemText(hwndDlg, IDC_METATRACK2, pVal);
782
 
        }
783
 
 
784
 
        pVal = NULL;
785
 
        if (mp4ff_meta_get_disc(file, &pVal))
786
 
        {
787
 
            SetDlgItemText(hwndDlg,IDC_METADISK1, pVal);
788
 
 
789
 
            //pVal = NULL;
790
 
            //mp4ff_meta_get_totaldiscs(file, &pVal);
791
 
            //SetDlgItemText(hwndDlg,IDC_METADISK2, pVal);
792
 
        }
793
 
 
794
 
        pVal = NULL;
795
 
        if (mp4ff_meta_get_date(file, &pVal))
796
 
            uSetDlgItemText(hwndDlg,IDC_METAYEAR, pVal);
797
 
 
798
 
#if 0
799
 
        /* WERKT NIET */
800
 
#endif
801
 
        pVal = NULL;
802
 
        if (mp4ff_meta_get_compilation(file, &pVal))
803
 
        {
804
 
            if (strcmp(pVal, "1") == 0)
805
 
            {
806
 
                SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
807
 
            }
808
 
        }
809
 
 
810
 
        /* ! Metadata */
811
 
 
812
 
        mp4ff_close(file);
813
 
        fclose(mp4File);
814
 
 
815
 
        return TRUE;
816
 
 
817
 
    case WM_COMMAND:
818
 
        switch (LOWORD(wParam)) {
819
 
        case IDCANCEL:
820
 
            EndDialog(hwndDlg, wParam);
821
 
            return TRUE;
822
 
        case IDOK:
823
 
 
824
 
            /* trying to edit currently playing file */
825
 
 
826
 
            if (!stricmp(info_fn, mp4state.filename))
827
 
            {
828
 
                MessageBox(module.hMainWindow, "Please stop playback before editing tags", "in_mp4", MB_ICONINFORMATION|MB_OK);
829
 
                return TRUE;
830
 
            }
831
 
 
832
 
            /* save Metadata changes */
833
 
 
834
 
            tag_delete(&tags);
835
 
 
836
 
            mp4File = fopen(info_fn, "rb");
837
 
            mp4cb.read = read_callback;
838
 
            mp4cb.seek = seek_callback;
839
 
            mp4cb.write = write_callback;
840
 
            mp4cb.truncate = truncate_callback;
841
 
            mp4cb.user_data = mp4File;
842
 
 
843
 
 
844
 
            file = mp4ff_open_read(&mp4cb);
845
 
            if (file != NULL)
846
 
            {
847
 
                ReadMP4Tag(file, &tags);
848
 
                mp4ff_close(file);
849
 
                fclose(mp4File);
850
 
            }
851
 
 
852
 
            mp4File = fopen(info_fn, "rb+");
853
 
            mp4cb.read = read_callback;
854
 
            mp4cb.seek = seek_callback;
855
 
            mp4cb.write = write_callback;
856
 
            mp4cb.truncate = truncate_callback;
857
 
            mp4cb.user_data = mp4File;
858
 
 
859
 
 
860
 
            uGetDlgItemText(hwndDlg, IDC_METANAME, dummy1, 1024);
861
 
            tag_set_field(&tags, "title", dummy1, strlen(dummy1));
862
 
 
863
 
            uGetDlgItemText(hwndDlg, IDC_METAWRITER, dummy1, 1024);
864
 
            tag_set_field(&tags, "writer", dummy1, strlen(dummy1));
865
 
 
866
 
            uGetDlgItemText(hwndDlg, IDC_METAARTIST, dummy1, 1024);
867
 
            tag_set_field(&tags, "artist", dummy1, strlen(dummy1));
868
 
 
869
 
            uGetDlgItemText(hwndDlg, IDC_METAALBUM, dummy1, 1024);
870
 
            tag_set_field(&tags, "album", dummy1, strlen(dummy1));
871
 
 
872
 
            uGetDlgItemText(hwndDlg, IDC_METACOMMENTS, dummy1, 1024);
873
 
            tag_set_field(&tags, "comment", dummy1, strlen(dummy1));
874
 
 
875
 
            uGetDlgItemText(hwndDlg, IDC_METAGENRE, dummy1, 1024);
876
 
            tag_set_field(&tags, "genre", dummy1, strlen(dummy1));
877
 
 
878
 
            uGetDlgItemText(hwndDlg, IDC_METAYEAR, dummy1, 1024);
879
 
            tag_set_field(&tags, "year", dummy1, strlen(dummy1));
880
 
 
881
 
            GetDlgItemText(hwndDlg, IDC_METATRACK1, dummy1, 1024);
882
 
            dummy = atoi(dummy1);
883
 
            //GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
884
 
            //dummy2 = atoi(dummy1);
885
 
            //wsprintf(temp, "%d/%d", dummy, dummy2);
886
 
            wsprintf(temp, "%d", dummy);
887
 
            tag_set_field(&tags, "track", temp, strlen(dummy1));
888
 
 
889
 
            GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024);
890
 
            dummy = atoi(dummy1);
891
 
            //GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
892
 
            //dummy2 = atoi(dummy1);
893
 
            //wsprintf(temp, "%d/%d", dummy, dummy2);
894
 
            wsprintf(temp, "%d", dummy);
895
 
            tag_set_field(&tags, "disc", temp, strlen(dummy1));
896
 
 
897
 
            dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0);
898
 
            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 1);
899
 
 
900
 
            mp4ff_meta_update(&mp4cb, &tags);
901
 
 
902
 
            fclose(mp4File);
903
 
 
904
 
            /* ! */
905
 
 
906
 
            EndDialog(hwndDlg, wParam);
907
 
            return TRUE;
908
 
        }
909
 
    }
910
 
    return FALSE;
911
 
}
912
 
 
913
 
/* returns the name of the object type */
914
 
char *get_ot_string(int ot)
915
 
{
916
 
    switch (ot)
917
 
    {
918
 
    case 0:
919
 
        return "Main";
920
 
    case 1:
921
 
        return "LC";
922
 
    case 2:
923
 
        return "SSR";
924
 
    case 3:
925
 
        return "LTP";
926
 
    }
927
 
    return NULL;
928
 
}
929
 
 
930
 
BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
931
 
                                   WPARAM wParam, LPARAM lParam)
932
 
{
933
 
    faadAACInfo aacInfo;
934
 
    char *info_text, *header_string;
935
 
 
936
 
#ifdef DEBUG_OUTPUT
937
 
    in_mp4_DebugOutput("aac_info_dialog_proc");
938
 
#endif
939
 
 
940
 
    switch (message) {
941
 
    case WM_INITDIALOG:
942
 
        EnableWindow(GetDlgItem(hwndDlg,IDC_USERDATA), FALSE) ;
943
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_USERDATA), SW_HIDE);
944
 
 
945
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC1), SW_HIDE);
946
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC2), SW_HIDE);
947
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC3), SW_HIDE);
948
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC4), SW_HIDE);
949
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC5), SW_HIDE);
950
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC6), SW_HIDE);
951
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC7), SW_HIDE);
952
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC8), SW_HIDE);
953
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC9), SW_HIDE);
954
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC10), SW_HIDE);
955
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC11), SW_HIDE);
956
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC12), SW_HIDE);
957
 
 
958
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METANAME), SW_HIDE);
959
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAARTIST), SW_HIDE);
960
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAWRITER), SW_HIDE);
961
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMMENTS), SW_HIDE);
962
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAALBUM), SW_HIDE);
963
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAGENRE), SW_HIDE);
964
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK1), SW_HIDE);
965
 
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
966
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK1), SW_HIDE);
967
 
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
968
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAYEAR), SW_HIDE);
969
 
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMPILATION), SW_HIDE);
970
 
 
971
 
        info_text = malloc(1024*sizeof(char));
972
 
 
973
 
        get_AAC_format(info_fn, &aacInfo);
974
 
 
975
 
        switch (aacInfo.headertype)
976
 
        {
977
 
        case 0: /* RAW */
978
 
            header_string = " RAW";
979
 
            break;
980
 
        case 1: /* ADIF */
981
 
            header_string = " ADIF";
982
 
            break;
983
 
        case 2: /* ADTS */
984
 
            header_string = " ADTS";
985
 
            break;
986
 
        }
987
 
 
988
 
        sprintf(info_text, "%s AAC %s%s, %d sec, %d kbps, %d Hz",
989
 
            (aacInfo.version==2)?"MPEG-2":"MPEG-4", get_ot_string(aacInfo.object_type),
990
 
            header_string,
991
 
            (int)((float)aacInfo.length/1000.0), (int)((float)aacInfo.bitrate/1000.0+0.5),
992
 
            aacInfo.sampling_rate);
993
 
 
994
 
        SetDlgItemText(hwndDlg, IDC_INFOTEXT, info_text);
995
 
 
996
 
        free(info_text);
997
 
 
998
 
        return TRUE;
999
 
 
1000
 
    case WM_COMMAND:
1001
 
        switch (LOWORD(wParam))
1002
 
        {
1003
 
        case IDCANCEL:
1004
 
        case IDOK:
1005
 
            EndDialog(hwndDlg, wParam);
1006
 
            return TRUE;
1007
 
        }
1008
 
    }
1009
 
    return FALSE;
1010
 
}
1011
 
 
1012
 
int infoDlg(char *fn, HWND hwndParent)
1013
 
{
1014
 
    if(!stricmp(fn + strlen(fn) - 3,"AAC"))
1015
 
    {
1016
 
        lstrcpy(info_fn, fn);
1017
 
 
1018
 
        DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
1019
 
            hwndParent, aac_info_dialog_proc);
1020
 
    } else {
1021
 
        lstrcpy(info_fn, fn);
1022
 
 
1023
 
        DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
1024
 
            hwndParent, mp4_info_dialog_proc);
1025
 
    }
1026
 
 
1027
 
    return 0;
1028
 
}
1029
 
 
1030
 
/* Get the title from the file */
1031
 
void ConstructTitle(mp4ff_t *file, char *filename, char *title, char *format)
1032
 
{
1033
 
    char temp[4096];
1034
 
    int some_info = 0;
1035
 
    char *in = format;
1036
 
    char *out = temp;//title;
1037
 
    char *bound = out + sizeof(temp) - 256; //out + (MAX_PATH - 10 - 1);
1038
 
    char *pVal, dummy1[1024];
1039
 
    short dummy, dummy2;
1040
 
 
1041
 
    while (*in && out < bound)
1042
 
    {
1043
 
        switch (*in)
1044
 
        {
1045
 
        case '%':
1046
 
            ++in;
1047
 
            break;
1048
 
 
1049
 
        default:
1050
 
            *out++ = *in++;
1051
 
            continue;
1052
 
        }
1053
 
 
1054
 
        /* handle % escape sequence */
1055
 
        switch (*in++)
1056
 
        {
1057
 
        case '0':
1058
 
            pVal = NULL;
1059
 
            if (mp4ff_meta_get_track(file, &pVal))
1060
 
            {
1061
 
                out += wsprintf(out, "%s", pVal);
1062
 
                some_info = 1;
1063
 
            }
1064
 
            break;
1065
 
 
1066
 
        case '1':
1067
 
            pVal = NULL;
1068
 
            if (mp4ff_meta_get_artist(file, &pVal))
1069
 
            {
1070
 
                out += wsprintf(out, "%s", pVal);
1071
 
                some_info = 1;
1072
 
            }
1073
 
            break;
1074
 
 
1075
 
        case '2':
1076
 
            pVal = NULL;
1077
 
            if (mp4ff_meta_get_title(file, &pVal))
1078
 
            {
1079
 
                out += wsprintf(out, "%s", pVal);
1080
 
                some_info = 1;
1081
 
            }
1082
 
            break;
1083
 
 
1084
 
        case '3':
1085
 
            pVal = NULL;
1086
 
            if (mp4ff_meta_get_album(file, &pVal))
1087
 
            {
1088
 
                out += wsprintf(out, "%s", pVal);
1089
 
                some_info = 1;
1090
 
            }
1091
 
            break;
1092
 
 
1093
 
        case '4':
1094
 
            pVal = NULL;
1095
 
            if (mp4ff_meta_get_date(file, &pVal))
1096
 
            {
1097
 
                out += wsprintf(out, "%s", pVal);
1098
 
                some_info = 1;
1099
 
            }
1100
 
            break;
1101
 
 
1102
 
        case '5':
1103
 
            pVal = NULL;
1104
 
            if (mp4ff_meta_get_comment(file, &pVal))
1105
 
            {
1106
 
                out += wsprintf(out, "%s", pVal);
1107
 
                some_info = 1;
1108
 
            }
1109
 
            break;
1110
 
 
1111
 
        case '6':
1112
 
            pVal = NULL;
1113
 
            if (mp4ff_meta_get_genre(file, &pVal))
1114
 
            {
1115
 
                out += wsprintf(out, "%s", pVal);
1116
 
                some_info = 1;
1117
 
            }
1118
 
            break;
1119
 
 
1120
 
        case '7':
1121
 
            {
1122
 
                const char *p=strrchr(filename,'\\');
1123
 
                if (!p) p=filename; else p++;
1124
 
                out += ConvertANSIToUTF8(p, out);
1125
 
                some_info = 1;
1126
 
                break;
1127
 
            }
1128
 
 
1129
 
        default:
1130
 
            break;
1131
 
        }
1132
 
    }
1133
 
 
1134
 
    *out = '\0';
1135
 
 
1136
 
    if (!some_info)
1137
 
    {
1138
 
        char *p=filename+lstrlen(filename);
1139
 
        while (*p != '\\' && p >= filename) p--;
1140
 
        lstrcpy(title,++p);
1141
 
    }
1142
 
    else
1143
 
    {
1144
 
        int len = ConvertUTF8ToANSI(temp, dummy1);
1145
 
        if (len > (MAX_PATH - 10 - 1)) len = (MAX_PATH - 10 - 1);
1146
 
        memcpy(title, dummy1, len);
1147
 
        title[len] = '\0';
1148
 
    }
1149
 
}
1150
 
 
1151
 
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message,
1152
 
                                 WPARAM wParam, LPARAM lParam)
1153
 
{
1154
 
    int i;
1155
 
 
1156
 
    switch (message) {
1157
 
    case WM_INITDIALOG:
1158
 
        SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETRANGE, TRUE, MAKELONG(1,5));
1159
 
        SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETPOS, TRUE, m_priority);
1160
 
        SendMessage(GetDlgItem(hwndDlg, res_id_table[m_resolution]), BM_SETCHECK, BST_CHECKED, 0);
1161
 
        if (m_show_errors)
1162
 
            SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_SETCHECK, BST_CHECKED, 0);
1163
 
        if (m_use_for_aac)
1164
 
            SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_SETCHECK, BST_CHECKED, 0);
1165
 
        if (m_downmix)
1166
 
            SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_SETCHECK, BST_CHECKED, 0);
1167
 
        if (m_vbr_display)
1168
 
            SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_SETCHECK, BST_CHECKED, 0);
1169
 
        SetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat);
1170
 
        return TRUE;
1171
 
 
1172
 
    case WM_COMMAND:
1173
 
        switch (LOWORD(wParam)) {
1174
 
        case IDCANCEL:
1175
 
            EndDialog(hwndDlg, wParam);
1176
 
            return TRUE;
1177
 
        case IDOK:
1178
 
            m_show_errors = SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_GETCHECK, 0, 0);
1179
 
            m_use_for_aac = SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_GETCHECK, 0, 0);
1180
 
            m_downmix = SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_GETCHECK, 0, 0);
1181
 
            m_vbr_display = SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_GETCHECK, 0, 0);
1182
 
            GetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat, MAX_PATH);
1183
 
 
1184
 
            m_priority = SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_GETPOS, 0, 0);
1185
 
            for (i = 0; i < 6; i++)
1186
 
            {
1187
 
                if (SendMessage(GetDlgItem(hwndDlg, res_id_table[i]), BM_GETCHECK, 0, 0))
1188
 
                {
1189
 
                    m_resolution = i;
1190
 
                    break;
1191
 
                }
1192
 
            }
1193
 
 
1194
 
            /* save config */
1195
 
            config_write();
1196
 
 
1197
 
            if (!m_use_for_aac)
1198
 
            {
1199
 
                module.FileExtensions = short_ext_list;
1200
 
            } else {
1201
 
                module.FileExtensions = long_ext_list;
1202
 
            }
1203
 
 
1204
 
            EndDialog(hwndDlg, wParam);
1205
 
            return TRUE;
1206
 
        }
1207
 
    }
1208
 
    return FALSE;
1209
 
}
1210
 
 
1211
 
void config(HWND hwndParent)
1212
 
{
1213
 
    DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG),
1214
 
        hwndParent, config_dialog_proc);
1215
 
 
1216
 
    return;
1217
 
}
1218
 
 
1219
 
void about(HWND hwndParent)
1220
 
{
1221
 
    MessageBox(hwndParent,
1222
 
        "AudioCoding.com MPEG-4 AAC player " FAAD2_VERSION " compiled on " __DATE__ ".\n"
1223
 
        "Visit the website for more info.\n"
1224
 
        "Copyright 2002-2004 AudioCoding.com",
1225
 
        "About",
1226
 
        MB_OK);
1227
 
}
1228
 
 
1229
 
int isourfile(char *fn)
1230
 
{
1231
 
    if (!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
1232
 
    {
1233
 
        return 1;
1234
 
    } else if (m_use_for_aac) {
1235
 
        if (!stricmp(fn + strlen(fn) - 3,"AAC"))
1236
 
        {
1237
 
            return 1;
1238
 
        }
1239
 
    }
1240
 
 
1241
 
    return 0;
1242
 
}
1243
 
 
1244
 
int fill_buffer(state *st)
1245
 
{
1246
 
    int bread;
1247
 
 
1248
 
    if (st->m_aac_bytes_consumed > 0)
1249
 
    {
1250
 
        if (st->m_aac_bytes_into_buffer)
1251
 
        {
1252
 
            memmove((void*)st->m_aac_buffer, (void*)(st->m_aac_buffer + st->m_aac_bytes_consumed),
1253
 
                st->m_aac_bytes_into_buffer*sizeof(unsigned char));
1254
 
        }
1255
 
 
1256
 
        if (!st->m_at_eof)
1257
 
        {
1258
 
            bread = fread((void*)(st->m_aac_buffer + st->m_aac_bytes_into_buffer),
1259
 
                1, st->m_aac_bytes_consumed, st->aacfile);
1260
 
 
1261
 
            if (bread != st->m_aac_bytes_consumed)
1262
 
                st->m_at_eof = 1;
1263
 
 
1264
 
            st->m_aac_bytes_into_buffer += bread;
1265
 
        }
1266
 
 
1267
 
        st->m_aac_bytes_consumed = 0;
1268
 
 
1269
 
        if (st->m_aac_bytes_into_buffer > 3)
1270
 
        {
1271
 
            if (memcmp(st->m_aac_buffer, "TAG", 3) == 0)
1272
 
                st->m_aac_bytes_into_buffer = 0;
1273
 
        }
1274
 
        if (st->m_aac_bytes_into_buffer > 11)
1275
 
        {
1276
 
            if (memcmp(st->m_aac_buffer, "LYRICSBEGIN", 11) == 0)
1277
 
                st->m_aac_bytes_into_buffer = 0;
1278
 
        }
1279
 
        if (st->m_aac_bytes_into_buffer > 8)
1280
 
        {
1281
 
            if (memcmp(st->m_aac_buffer, "APETAGEX", 8) == 0)
1282
 
                st->m_aac_bytes_into_buffer = 0;
1283
 
        }
1284
 
    }
1285
 
 
1286
 
    return 1;
1287
 
}
1288
 
 
1289
 
void advance_buffer(state *st, int bytes)
1290
 
{
1291
 
    st->m_file_offset += bytes;
1292
 
    st->m_aac_bytes_consumed = bytes;
1293
 
    st->m_aac_bytes_into_buffer -= bytes;
1294
 
}
1295
 
 
1296
 
int adts_parse(state *st, __int64 *bitrate, double *length)
1297
 
{
1298
 
    static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
1299
 
    int frames, frame_length;
1300
 
    int t_framelength = 0;
1301
 
    int samplerate;
1302
 
    double frames_per_sec, bytes_per_frame;
1303
 
 
1304
 
    /* Read all frames to ensure correct time and bitrate */
1305
 
    for (frames = 0; /* */; frames++)
1306
 
    {
1307
 
        fill_buffer(st);
1308
 
 
1309
 
        if (st->m_aac_bytes_into_buffer > 7)
1310
 
        {
1311
 
            /* check syncword */
1312
 
            if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
1313
 
                break;
1314
 
 
1315
 
            st->m_tail->offset = st->m_file_offset;
1316
 
            st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
1317
 
            st->m_tail = st->m_tail->next;
1318
 
            st->m_tail->next = NULL;
1319
 
 
1320
 
            if (frames == 0)
1321
 
                samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];
1322
 
 
1323
 
            frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
1324
 
                | (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);
1325
 
 
1326
 
            t_framelength += frame_length;
1327
 
 
1328
 
            if (frame_length > st->m_aac_bytes_into_buffer)
1329
 
                break;
1330
 
 
1331
 
            advance_buffer(st, frame_length);
1332
 
        } else {
1333
 
            break;
1334
 
        }
1335
 
    }
1336
 
 
1337
 
    frames_per_sec = (double)samplerate/1024.0;
1338
 
    if (frames != 0)
1339
 
        bytes_per_frame = (double)t_framelength/(double)(frames*1000);
1340
 
    else
1341
 
        bytes_per_frame = 0;
1342
 
    *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
1343
 
    if (frames_per_sec != 0)
1344
 
        *length = (double)frames/frames_per_sec;
1345
 
    else
1346
 
        *length = 1;
1347
 
 
1348
 
    return 1;
1349
 
}
1350
 
 
1351
 
int skip_id3v2_tag()
1352
 
{
1353
 
    unsigned char buf[10];
1354
 
    int bread, tagsize = 0;
1355
 
 
1356
 
    bread = fread(buf, 1, 10, mp4state.aacfile);
1357
 
    if (bread != 10) return -1;
1358
 
 
1359
 
    if (!memcmp(buf, "ID3", 3))
1360
 
    {
1361
 
        /* high bit is not used */
1362
 
        tagsize = (buf[6] << 21) | (buf[7] << 14) | (buf[8] << 7) | (buf[9] << 0);
1363
 
 
1364
 
        tagsize += 10;
1365
 
        fseek(mp4state.aacfile, tagsize, SEEK_SET);
1366
 
    } else {
1367
 
        fseek(mp4state.aacfile, 0, SEEK_SET);
1368
 
    }
1369
 
 
1370
 
    return tagsize;
1371
 
}
1372
 
 
1373
 
int play(char *fn)
1374
 
{
1375
 
    int maxlatency;
1376
 
    int thread_id;
1377
 
    int avg_bitrate, br, sr;
1378
 
    unsigned char *buffer;
1379
 
    int buffer_size;
1380
 
    NeAACDecConfigurationPtr config;
1381
 
    unsigned char header[8];
1382
 
    FILE *hMP4File;
1383
 
 
1384
 
#ifdef DEBUG_OUTPUT
1385
 
    in_mp4_DebugOutput("play");
1386
 
#endif
1387
 
 
1388
 
    memset(&mp4state, 0, sizeof(state));
1389
 
 
1390
 
    lstrcpy(mp4state.filename, fn);
1391
 
 
1392
 
    hMP4File = fopen(mp4state.filename, "rb");
1393
 
    if (!hMP4File)
1394
 
    {
1395
 
        return -1;
1396
 
    }
1397
 
    fread(header, 1, 8, hMP4File);
1398
 
    fclose(hMP4File);
1399
 
    mp4state.filetype = 1;
1400
 
    if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
1401
 
        mp4state.filetype = 0;
1402
 
 
1403
 
    if (mp4state.filetype)
1404
 
    {
1405
 
        int tagsize = 0, tmp = 0, init;
1406
 
        int bread = 0;
1407
 
        double length = 0.;
1408
 
        __int64 bitrate = 128;
1409
 
//        NeAACDecFrameInfo frameInfo;
1410
 
 
1411
 
        module.is_seekable = 1;
1412
 
 
1413
 
        if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
1414
 
        {
1415
 
            // error
1416
 
            return -1;
1417
 
        }
1418
 
 
1419
 
        tagsize = skip_id3v2_tag();
1420
 
        if (tagsize<0) return 0;
1421
 
 
1422
 
        if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
1423
 
        {
1424
 
            show_error(module.hMainWindow, "Memory allocation error.");
1425
 
            return -1;
1426
 
        }
1427
 
 
1428
 
        for (init=0; init<2; init++)
1429
 
        {
1430
 
            mp4state.hDecoder = NeAACDecOpen();
1431
 
            if (!mp4state.hDecoder)
1432
 
            {
1433
 
                show_error(module.hMainWindow, "Unable to open decoder library.");
1434
 
                return -1;
1435
 
            }
1436
 
 
1437
 
            config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
1438
 
            config->outputFormat = m_resolution + 1;
1439
 
            config->downMatrix = m_downmix;
1440
 
            NeAACDecSetConfiguration(mp4state.hDecoder, config);
1441
 
 
1442
 
            memset(mp4state.m_aac_buffer, 0, 768*6);
1443
 
            bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
1444
 
            mp4state.m_aac_bytes_into_buffer = bread;
1445
 
            mp4state.m_aac_bytes_consumed = 0;
1446
 
            mp4state.m_file_offset = 0;
1447
 
            mp4state.m_at_eof = (bread != 768*6) ? 1 : 0;
1448
 
 
1449
 
            if (init==0)
1450
 
            {
1451
 
                NeAACDecFrameInfo frameInfo;
1452
 
 
1453
 
                fill_buffer(&mp4state);
1454
 
 
1455
 
                if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
1456
 
                    mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
1457
 
                    &mp4state.samplerate, &mp4state.channels)) < 0)
1458
 
                {
1459
 
                    show_error(module.hMainWindow, "Can't initialize decoder library.");
1460
 
                    return -1;
1461
 
                }
1462
 
                advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
1463
 
 
1464
 
                do {
1465
 
                    memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
1466
 
                    fill_buffer(&mp4state);
1467
 
                    NeAACDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
1468
 
                } while (!frameInfo.samples && !frameInfo.error);
1469
 
 
1470
 
                if (frameInfo.error)
1471
 
                {
1472
 
                    show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
1473
 
                    return -1;
1474
 
                }
1475
 
 
1476
 
                mp4state.channels = frameInfo.channels;
1477
 
                mp4state.samplerate = frameInfo.samplerate;
1478
 
                mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
1479
 
                /*
1480
 
                sbr = frameInfo.sbr;
1481
 
                profile = frameInfo.object_type;
1482
 
                header_type = frameInfo.header_type;
1483
 
                */
1484
 
 
1485
 
                NeAACDecClose(mp4state.hDecoder);
1486
 
                fseek(mp4state.aacfile, tagsize, SEEK_SET);
1487
 
            }
1488
 
        }
1489
 
 
1490
 
        mp4state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
1491
 
        mp4state.m_tail = mp4state.m_head;
1492
 
        mp4state.m_tail->next = NULL;
1493
 
 
1494
 
        mp4state.m_header_type = 0;
1495
 
        if ((mp4state.m_aac_buffer[0] == 0xFF) && ((mp4state.m_aac_buffer[1] & 0xF6) == 0xF0))
1496
 
        {
1497
 
            if (1) //(can_seek)
1498
 
            {
1499
 
                adts_parse(&mp4state, &bitrate, &length);
1500
 
                fseek(mp4state.aacfile, tagsize, SEEK_SET);
1501
 
 
1502
 
                bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
1503
 
                if (bread != 768*6)
1504
 
                    mp4state.m_at_eof = 1;
1505
 
                else
1506
 
                    mp4state.m_at_eof = 0;
1507
 
                mp4state.m_aac_bytes_into_buffer = bread;
1508
 
                mp4state.m_aac_bytes_consumed = 0;
1509
 
 
1510
 
                mp4state.m_header_type = 1;
1511
 
            }
1512
 
        } else if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0) {
1513
 
            int skip_size = (mp4state.m_aac_buffer[4] & 0x80) ? 9 : 0;
1514
 
            bitrate = ((unsigned int)(mp4state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
1515
 
                ((unsigned int)mp4state.m_aac_buffer[5 + skip_size]<<11) |
1516
 
                ((unsigned int)mp4state.m_aac_buffer[6 + skip_size]<<3) |
1517
 
                ((unsigned int)mp4state.m_aac_buffer[7 + skip_size] & 0xE0);
1518
 
 
1519
 
            length = (double)file_length(mp4state.aacfile);
1520
 
            if (length == -1)
1521
 
            {
1522
 
                module.is_seekable = 0;
1523
 
                length = 0;
1524
 
            } else {
1525
 
                length = ((double)length*8.)/((double)bitrate) + 0.5;
1526
 
            }
1527
 
 
1528
 
            mp4state.m_header_type = 2;
1529
 
        } else {
1530
 
            length = (double)file_length(mp4state.aacfile);
1531
 
            length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
1532
 
 
1533
 
            module.is_seekable = 1;
1534
 
        }
1535
 
 
1536
 
        mp4state.m_length = (int)(length*1000.);
1537
 
 
1538
 
        fill_buffer(&mp4state);
1539
 
        if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
1540
 
            mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
1541
 
            &mp4state.samplerate, &mp4state.channels)) < 0)
1542
 
        {
1543
 
            show_error(module.hMainWindow, "Can't initialize decoder library.");
1544
 
            return -1;
1545
 
        }
1546
 
        advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
1547
 
 
1548
 
        if (mp4state.m_header_type == 2)
1549
 
            avg_bitrate = bitrate;
1550
 
        else
1551
 
            avg_bitrate = bitrate*1000;
1552
 
    } else {
1553
 
        mp4state.hDecoder = NeAACDecOpen();
1554
 
        if (!mp4state.hDecoder)
1555
 
        {
1556
 
            show_error(module.hMainWindow, "Unable to open decoder library.");
1557
 
            return -1;
1558
 
        }
1559
 
 
1560
 
        config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
1561
 
        config->outputFormat = m_resolution + 1;
1562
 
        config->downMatrix = m_downmix;
1563
 
        NeAACDecSetConfiguration(mp4state.hDecoder, config);
1564
 
 
1565
 
        mp4state.mp4File = fopen(mp4state.filename, "rb");
1566
 
        mp4state.mp4cb.read = read_callback;
1567
 
        mp4state.mp4cb.seek = seek_callback;
1568
 
        mp4state.mp4cb.user_data = mp4state.mp4File;
1569
 
 
1570
 
 
1571
 
        mp4state.mp4file = mp4ff_open_read(&mp4state.mp4cb);
1572
 
        if (!mp4state.mp4file)
1573
 
        {
1574
 
            show_error(module.hMainWindow, "Unable to open file.");
1575
 
            NeAACDecClose(mp4state.hDecoder);
1576
 
            return -1;
1577
 
        }
1578
 
 
1579
 
        if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
1580
 
        {
1581
 
            show_error(module.hMainWindow, "Unsupported Audio track type.");
1582
 
            NeAACDecClose(mp4state.hDecoder);
1583
 
            mp4ff_close(mp4state.mp4file);
1584
 
            fclose(mp4state.mp4File);
1585
 
            return -1;
1586
 
        }
1587
 
 
1588
 
        buffer = NULL;
1589
 
        buffer_size = 0;
1590
 
        mp4ff_get_decoder_config(mp4state.mp4file, mp4state.mp4track,
1591
 
            &buffer, &buffer_size);
1592
 
        if (!buffer)
1593
 
        {
1594
 
            NeAACDecClose(mp4state.hDecoder);
1595
 
            mp4ff_close(mp4state.mp4file);
1596
 
            fclose(mp4state.mp4File);
1597
 
            return -1;
1598
 
        }
1599
 
 
1600
 
        if(NeAACDecInit2(mp4state.hDecoder, buffer, buffer_size,
1601
 
            &mp4state.samplerate, &mp4state.channels) < 0)
1602
 
        {
1603
 
            /* If some error initializing occured, skip the file */
1604
 
            NeAACDecClose(mp4state.hDecoder);
1605
 
            mp4ff_close(mp4state.mp4file);
1606
 
            fclose(mp4state.mp4File);
1607
 
            if (buffer) free (buffer);
1608
 
            return -1;
1609
 
        }
1610
 
 
1611
 
        /* for gapless decoding */
1612
 
        {
1613
 
            mp4AudioSpecificConfig mp4ASC;
1614
 
 
1615
 
            mp4state.timescale = mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
1616
 
            mp4state.framesize = 1024;
1617
 
            mp4state.useAacLength = 0;
1618
 
 
1619
 
            if (buffer)
1620
 
            {
1621
 
                if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
1622
 
                {
1623
 
                    if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
1624
 
                    if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
1625
 
                }
1626
 
            }
1627
 
        }
1628
 
 
1629
 
        free(buffer);
1630
 
 
1631
 
        avg_bitrate = mp4ff_get_avg_bitrate(mp4state.mp4file, mp4state.mp4track);
1632
 
 
1633
 
        mp4state.numSamples = mp4ff_num_samples(mp4state.mp4file, mp4state.mp4track);
1634
 
        mp4state.sampleId = 0;
1635
 
 
1636
 
        {
1637
 
            double timescale_div = 1.0 / (double)mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
1638
 
            int64_t duration = mp4ff_get_track_duration_use_offsets(mp4state.mp4file, mp4state.mp4track);
1639
 
            if (duration == -1)
1640
 
            {
1641
 
                mp4state.m_length = 0;
1642
 
            } else {
1643
 
                mp4state.m_length = (int)((double)duration * timescale_div * 1000.0);
1644
 
            }
1645
 
        }
1646
 
 
1647
 
        module.is_seekable = 1;
1648
 
    }
1649
 
 
1650
 
    if (mp4state.channels == 0)
1651
 
    {
1652
 
        show_error(module.hMainWindow, "Number of channels not supported for playback.");
1653
 
        NeAACDecClose(mp4state.hDecoder);
1654
 
        if (mp4state.filetype)
1655
 
            fclose(mp4state.aacfile);
1656
 
        else {
1657
 
            mp4ff_close(mp4state.mp4file);
1658
 
            fclose(mp4state.mp4File);
1659
 
        }
1660
 
        return -1;
1661
 
    }
1662
 
 
1663
 
    if (m_downmix && (mp4state.channels == 5 || mp4state.channels == 6))
1664
 
        mp4state.channels = 2;
1665
 
 
1666
 
    maxlatency = module.outMod->Open(mp4state.samplerate, (int)mp4state.channels,
1667
 
        res_table[m_resolution], -1, -1);
1668
 
 
1669
 
    if (maxlatency < 0) // error opening device
1670
 
    {
1671
 
        NeAACDecClose(mp4state.hDecoder);
1672
 
        if (mp4state.filetype)
1673
 
            fclose(mp4state.aacfile);
1674
 
        else {
1675
 
            mp4ff_close(mp4state.mp4file);
1676
 
            fclose(mp4state.mp4File);
1677
 
        }
1678
 
        return -1;
1679
 
    }
1680
 
 
1681
 
    mp4state.paused        =  0;
1682
 
    mp4state.decode_pos_ms =  0;
1683
 
    mp4state.seek_needed   = -1;
1684
 
 
1685
 
    // initialize vis stuff
1686
 
    module.SAVSAInit(maxlatency, mp4state.samplerate);
1687
 
    module.VSASetInfo((int)mp4state.channels, mp4state.samplerate);
1688
 
 
1689
 
    br = (int)floor(((float)avg_bitrate + 500.0)/1000.0 + 0.5);
1690
 
    sr = (int)floor((float)mp4state.samplerate/1000.0 + 0.5);
1691
 
    module.SetInfo(br, sr, (int)mp4state.channels, 1);
1692
 
 
1693
 
    module.outMod->SetVolume(-666); // set the output plug-ins default volume
1694
 
 
1695
 
    killPlayThread = 0;
1696
 
 
1697
 
    if (mp4state.filetype)
1698
 
    {
1699
 
        if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AACPlayThread,
1700
 
            (void *)&killPlayThread, 0, &thread_id)) == NULL)
1701
 
        {
1702
 
            show_error(module.hMainWindow, "Cannot create playback thread");
1703
 
            NeAACDecClose(mp4state.hDecoder);
1704
 
            fclose(mp4state.aacfile);
1705
 
            return -1;
1706
 
        }
1707
 
    } else {
1708
 
        if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MP4PlayThread,
1709
 
            (void *)&killPlayThread, 0, &thread_id)) == NULL)
1710
 
        {
1711
 
            show_error(module.hMainWindow, "Cannot create playback thread");
1712
 
            NeAACDecClose(mp4state.hDecoder);
1713
 
            mp4ff_close(mp4state.mp4file);
1714
 
            fclose(mp4state.mp4File);
1715
 
            return -1;
1716
 
        }
1717
 
    }
1718
 
 
1719
 
    SetThreadAffinityMask(play_thread_handle, 1);
1720
 
 
1721
 
    SetThreadPriority(play_thread_handle, priority_table[m_priority]);
1722
 
 
1723
 
    return 0;
1724
 
}
1725
 
 
1726
 
void pause()
1727
 
{
1728
 
#ifdef DEBUG_OUTPUT
1729
 
    in_mp4_DebugOutput("pause");
1730
 
#endif
1731
 
 
1732
 
    mp4state.paused = 1;
1733
 
    module.outMod->Pause(1);
1734
 
}
1735
 
 
1736
 
void unpause()
1737
 
{
1738
 
#ifdef DEBUG_OUTPUT
1739
 
    in_mp4_DebugOutput("unpause");
1740
 
#endif
1741
 
 
1742
 
    mp4state.paused = 0;
1743
 
    module.outMod->Pause(0);
1744
 
}
1745
 
 
1746
 
int ispaused()
1747
 
{
1748
 
#ifdef DEBUG_OUTPUT
1749
 
    in_mp4_DebugOutput("ispaused");
1750
 
#endif
1751
 
 
1752
 
    return mp4state.paused;
1753
 
}
1754
 
 
1755
 
void setvolume(int volume)
1756
 
{
1757
 
#ifdef DEBUG_OUTPUT
1758
 
    in_mp4_DebugOutput("setvolume");
1759
 
#endif
1760
 
 
1761
 
    module.outMod->SetVolume(volume);
1762
 
}
1763
 
 
1764
 
void setpan(int pan)
1765
 
{
1766
 
#ifdef DEBUG_OUTPUT
1767
 
    in_mp4_DebugOutput("setpan");
1768
 
#endif
1769
 
 
1770
 
    module.outMod->SetPan(pan);
1771
 
}
1772
 
 
1773
 
void stop()
1774
 
{
1775
 
    struct seek_list *target = mp4state.m_head;
1776
 
 
1777
 
#ifdef DEBUG_OUTPUT
1778
 
    in_mp4_DebugOutput("stop");
1779
 
#endif
1780
 
 
1781
 
    killPlayThread = 1;
1782
 
 
1783
 
    if (play_thread_handle != INVALID_HANDLE_VALUE)
1784
 
    {
1785
 
        if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
1786
 
            TerminateThread(play_thread_handle,0);
1787
 
        CloseHandle(play_thread_handle);
1788
 
        play_thread_handle = INVALID_HANDLE_VALUE;
1789
 
    }
1790
 
 
1791
 
 
1792
 
    if (mp4state.m_aac_buffer)
1793
 
        free(mp4state.m_aac_buffer);
1794
 
 
1795
 
    while (target)
1796
 
    {
1797
 
        struct seek_list *tmp = target;
1798
 
        target = target->next;
1799
 
        if (tmp) free(tmp);
1800
 
    }
1801
 
    NeAACDecClose(mp4state.hDecoder);
1802
 
    if (mp4state.filetype)
1803
 
        fclose(mp4state.aacfile);
1804
 
    else {
1805
 
        mp4ff_close(mp4state.mp4file);
1806
 
        fclose(mp4state.mp4File);
1807
 
    }
1808
 
 
1809
 
    module.outMod->Close();
1810
 
    module.SAVSADeInit();
1811
 
 
1812
 
    mp4state.filename[0] = '\0';
1813
 
}
1814
 
 
1815
 
int getsonglength(const char *fn)
1816
 
{
1817
 
    long msDuration = 0;
1818
 
 
1819
 
    if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
1820
 
    {
1821
 
        int track;
1822
 
        int64_t length;
1823
 
        FILE *mp4File;
1824
 
        mp4ff_t *file;
1825
 
        mp4ff_callback_t mp4cb = {0};
1826
 
 
1827
 
        mp4File = fopen(fn, "rb");
1828
 
        mp4cb.read = read_callback;
1829
 
        mp4cb.seek = seek_callback;
1830
 
        mp4cb.user_data = mp4File;
1831
 
 
1832
 
 
1833
 
        file = mp4ff_open_read(&mp4cb);
1834
 
        if (file == NULL)
1835
 
            return 0;
1836
 
 
1837
 
        if ((track = GetAACTrack(file)) < 0)
1838
 
        {
1839
 
            mp4ff_close(file);
1840
 
            fclose(mp4File);
1841
 
            return -1;
1842
 
        }
1843
 
 
1844
 
        length = mp4ff_get_track_duration(file, track);
1845
 
 
1846
 
        msDuration = (long)((float)length*1000.0 / (float)mp4ff_time_scale(file, track) + 0.5);
1847
 
 
1848
 
        mp4ff_close(file);
1849
 
        fclose(mp4File);
1850
 
 
1851
 
        return msDuration;
1852
 
    } else {
1853
 
        int tagsize = 0;
1854
 
        int bread = 0;
1855
 
        double length = 0.;
1856
 
        __int64 bitrate = 128;
1857
 
        struct seek_list *target;
1858
 
        state len_state;
1859
 
 
1860
 
        memset(&len_state, 0, sizeof(state));
1861
 
 
1862
 
        if (!(len_state.aacfile = fopen(fn, "rb")))
1863
 
        {
1864
 
            // error
1865
 
            return 0;
1866
 
        }
1867
 
 
1868
 
        len_state.m_at_eof = 0;
1869
 
 
1870
 
        if (!(len_state.m_aac_buffer = (unsigned char*)malloc(768*6)))
1871
 
        {
1872
 
            //console::error("Memory allocation error.", "foo_mp4");
1873
 
            return 0;
1874
 
        }
1875
 
        memset(len_state.m_aac_buffer, 0, 768*6);
1876
 
 
1877
 
        bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
1878
 
        len_state.m_aac_bytes_into_buffer = bread;
1879
 
        len_state.m_aac_bytes_consumed = 0;
1880
 
        len_state.m_file_offset = 0;
1881
 
 
1882
 
        if (bread != 768*6)
1883
 
            len_state.m_at_eof = 1;
1884
 
 
1885
 
        if (!memcmp(len_state.m_aac_buffer, "ID3", 3))
1886
 
        {
1887
 
            /* high bit is not used */
1888
 
            tagsize = (len_state.m_aac_buffer[6] << 21) | (len_state.m_aac_buffer[7] << 14) |
1889
 
                (len_state.m_aac_buffer[8] <<  7) | (len_state.m_aac_buffer[9] <<  0);
1890
 
 
1891
 
            tagsize += 10;
1892
 
            advance_buffer(&len_state, tagsize);
1893
 
        }
1894
 
 
1895
 
        len_state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
1896
 
        len_state.m_tail = len_state.m_head;
1897
 
        len_state.m_tail->next = NULL;
1898
 
 
1899
 
        len_state.m_header_type = 0;
1900
 
        if ((len_state.m_aac_buffer[0] == 0xFF) && ((len_state.m_aac_buffer[1] & 0xF6) == 0xF0))
1901
 
        {
1902
 
            if (1) //(m_reader->can_seek())
1903
 
            {
1904
 
                adts_parse(&len_state, &bitrate, &length);
1905
 
                fseek(len_state.aacfile, tagsize, SEEK_SET);
1906
 
 
1907
 
                bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
1908
 
                if (bread != 768*6)
1909
 
                    len_state.m_at_eof = 1;
1910
 
                else
1911
 
                    len_state.m_at_eof = 0;
1912
 
                len_state.m_aac_bytes_into_buffer = bread;
1913
 
                len_state.m_aac_bytes_consumed = 0;
1914
 
 
1915
 
                len_state.m_header_type = 1;
1916
 
            }
1917
 
        } else if (memcmp(len_state.m_aac_buffer, "ADIF", 4) == 0) {
1918
 
            int skip_size = (len_state.m_aac_buffer[4] & 0x80) ? 9 : 0;
1919
 
            bitrate = ((unsigned int)(len_state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
1920
 
                ((unsigned int)len_state.m_aac_buffer[5 + skip_size]<<11) |
1921
 
                ((unsigned int)len_state.m_aac_buffer[6 + skip_size]<<3) |
1922
 
                ((unsigned int)len_state.m_aac_buffer[7 + skip_size] & 0xE0);
1923
 
 
1924
 
            length = (double)file_length(len_state.aacfile);
1925
 
            if (length == -1)
1926
 
                length = 0;
1927
 
            else
1928
 
                length = ((double)length*8.)/((double)bitrate) + 0.5;
1929
 
 
1930
 
            len_state.m_header_type = 2;
1931
 
        } else {
1932
 
            length = (double)file_length(len_state.aacfile);
1933
 
            length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
1934
 
 
1935
 
            len_state.m_header_type = 0;
1936
 
        }
1937
 
 
1938
 
        if (len_state.m_aac_buffer)
1939
 
            free(len_state.m_aac_buffer);
1940
 
 
1941
 
        target = len_state.m_head;
1942
 
        while (target)
1943
 
        {
1944
 
            struct seek_list *tmp = target;
1945
 
            target = target->next;
1946
 
            if (tmp) free(tmp);
1947
 
        }
1948
 
 
1949
 
        fclose(len_state.aacfile);
1950
 
 
1951
 
        return (int)(length*1000.);
1952
 
    }
1953
 
}
1954
 
 
1955
 
int getlength()
1956
 
{
1957
 
    if (!mp4state.filetype)
1958
 
    {
1959
 
        int track;
1960
 
        long msDuration;
1961
 
        long length;
1962
 
 
1963
 
        if ((track = GetAACTrack(mp4state.mp4file)) < 0)
1964
 
        {
1965
 
            return -1;
1966
 
        }
1967
 
 
1968
 
        length = mp4ff_get_track_duration(mp4state.mp4file, track);
1969
 
 
1970
 
        msDuration = (long)(length*1000.0 / (float)mp4ff_time_scale(mp4state.mp4file, track) + 0.5);
1971
 
 
1972
 
        return msDuration;
1973
 
    } else {
1974
 
        return mp4state.m_length;
1975
 
    }
1976
 
    return 0;
1977
 
}
1978
 
 
1979
 
int getoutputtime()
1980
 
{
1981
 
    return mp4state.decode_pos_ms+(module.outMod->GetOutputTime()-module.outMod->GetWrittenTime());
1982
 
}
1983
 
 
1984
 
void setoutputtime(int time_in_ms)
1985
 
{
1986
 
#ifdef DEBUG_OUTPUT
1987
 
    in_mp4_DebugOutput("setoutputtime");
1988
 
#endif
1989
 
 
1990
 
    mp4state.seek_needed = time_in_ms;
1991
 
}
1992
 
 
1993
 
void getfileinfo(char *filename, char *title, int *length_in_ms)
1994
 
{
1995
 
    if (!filename || !*filename)  /* currently playing file */
1996
 
    {
1997
 
        if (length_in_ms)
1998
 
            *length_in_ms = getlength();
1999
 
 
2000
 
        if (title)
2001
 
        {
2002
 
            if (mp4state.filetype == 0)
2003
 
            {
2004
 
                ConstructTitle(mp4state.mp4file, mp4state.filename, title, titleformat);
2005
 
            } else {
2006
 
                char *tmp2;
2007
 
                char *tmp = PathFindFileName(mp4state.filename);
2008
 
                strcpy(title, tmp);
2009
 
                tmp2 = strrchr(title, '.');
2010
 
                tmp2[0] = '\0';
2011
 
            }
2012
 
        }
2013
 
    } else {
2014
 
        if (length_in_ms)
2015
 
            *length_in_ms = getsonglength(filename);
2016
 
 
2017
 
        if (title)
2018
 
        {
2019
 
            unsigned char header[8];
2020
 
            FILE *hMP4File = fopen(filename, "rb");
2021
 
            if (!hMP4File)
2022
 
            {
2023
 
                return;
2024
 
            }
2025
 
            fread(header, 1, 8, hMP4File);
2026
 
            fclose(hMP4File);
2027
 
 
2028
 
            if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
2029
 
            {
2030
 
                FILE *mp4File;
2031
 
                mp4ff_t *file;
2032
 
                mp4ff_callback_t mp4cb = {0};
2033
 
 
2034
 
                mp4File = fopen(filename, "rb");
2035
 
                mp4cb.read = read_callback;
2036
 
                mp4cb.seek = seek_callback;
2037
 
                mp4cb.user_data = mp4File;
2038
 
 
2039
 
                file = mp4ff_open_read(&mp4cb);
2040
 
                if (file == NULL)
2041
 
                    return;
2042
 
 
2043
 
                ConstructTitle(file, filename, title, titleformat);
2044
 
 
2045
 
                mp4ff_close(file);
2046
 
                fclose(mp4File);
2047
 
            } else {
2048
 
                char *tmp2;
2049
 
                char *tmp = PathFindFileName(filename);
2050
 
                strcpy(title, tmp);
2051
 
                tmp2 = strrchr(title, '.');
2052
 
                tmp2[0] = '\0';
2053
 
            }
2054
 
        }
2055
 
    }
2056
 
}
2057
 
 
2058
 
void eq_set(int on, char data[10], int preamp)
2059
 
{
2060
 
}
2061
 
 
2062
 
static void remap_channels(unsigned char *data, unsigned int samples, unsigned int bps)
2063
 
{
2064
 
    unsigned int i;
2065
 
 
2066
 
    switch (bps)
2067
 
    {
2068
 
    case 8:
2069
 
        {
2070
 
            unsigned char r1, r2, r3, r4, r5, r6;
2071
 
            for (i = 0; i < samples; i += 6)
2072
 
            {
2073
 
                r1 = data[i];
2074
 
                r2 = data[i+1];
2075
 
                r3 = data[i+2];
2076
 
                r4 = data[i+3];
2077
 
                r5 = data[i+4];
2078
 
                r6 = data[i+5];
2079
 
                data[i] = r2;
2080
 
                data[i+1] = r3;
2081
 
                data[i+2] = r1;
2082
 
                data[i+3] = r6;
2083
 
                data[i+4] = r4;
2084
 
                data[i+5] = r5;
2085
 
            }
2086
 
        }
2087
 
        break;
2088
 
 
2089
 
    case 16:
2090
 
    default:
2091
 
        {
2092
 
            unsigned short r1, r2, r3, r4, r5, r6;
2093
 
            unsigned short *sample_buffer = (unsigned short *)data;
2094
 
            for (i = 0; i < samples; i += 6)
2095
 
            {
2096
 
                r1 = sample_buffer[i];
2097
 
                r2 = sample_buffer[i+1];
2098
 
                r3 = sample_buffer[i+2];
2099
 
                r4 = sample_buffer[i+3];
2100
 
                r5 = sample_buffer[i+4];
2101
 
                r6 = sample_buffer[i+5];
2102
 
                sample_buffer[i] = r2;
2103
 
                sample_buffer[i+1] = r3;
2104
 
                sample_buffer[i+2] = r1;
2105
 
                sample_buffer[i+3] = r6;
2106
 
                sample_buffer[i+4] = r4;
2107
 
                sample_buffer[i+5] = r5;
2108
 
            }
2109
 
        }
2110
 
        break;
2111
 
 
2112
 
    case 24:
2113
 
    case 32:
2114
 
        {
2115
 
            unsigned int r1, r2, r3, r4, r5, r6;
2116
 
            unsigned int *sample_buffer = (unsigned int *)data;
2117
 
            for (i = 0; i < samples; i += 6)
2118
 
            {
2119
 
                r1 = sample_buffer[i];
2120
 
                r2 = sample_buffer[i+1];
2121
 
                r3 = sample_buffer[i+2];
2122
 
                r4 = sample_buffer[i+3];
2123
 
                r5 = sample_buffer[i+4];
2124
 
                r6 = sample_buffer[i+5];
2125
 
                sample_buffer[i] = r2;
2126
 
                sample_buffer[i+1] = r3;
2127
 
                sample_buffer[i+2] = r1;
2128
 
                sample_buffer[i+3] = r6;
2129
 
                sample_buffer[i+4] = r4;
2130
 
                sample_buffer[i+5] = r5;
2131
 
            }
2132
 
        }
2133
 
        break;
2134
 
    }
2135
 
}
2136
 
 
2137
 
DWORD WINAPI MP4PlayThread(void *b)
2138
 
{
2139
 
    int done = 0;
2140
 
    int l;
2141
 
    int seq_frames = 0;
2142
 
    int seq_bytes = 0;
2143
 
 
2144
 
    void *sample_buffer;
2145
 
    unsigned char *buffer;
2146
 
    int buffer_size;
2147
 
    NeAACDecFrameInfo frameInfo;
2148
 
 
2149
 
#ifdef DEBUG_OUTPUT
2150
 
    in_mp4_DebugOutput("MP4PlayThread");
2151
 
#endif
2152
 
 
2153
 
    PlayThreadAlive = 1;
2154
 
    mp4state.last_frame = 0;
2155
 
    mp4state.initial = 1;
2156
 
 
2157
 
    while (!*((int *)b))
2158
 
    {
2159
 
        /* seeking */
2160
 
        if (mp4state.seek_needed != -1)
2161
 
        {
2162
 
            int64_t duration;
2163
 
            int32_t skip_samples = 0;
2164
 
 
2165
 
            module.outMod->Flush(mp4state.decode_pos_ms);
2166
 
            duration = (int64_t)(mp4state.seek_needed/1000.0 * mp4state.samplerate + 0.5);
2167
 
            mp4state.sampleId = mp4ff_find_sample_use_offsets(mp4state.mp4file,
2168
 
                mp4state.mp4track, duration, &skip_samples);
2169
 
 
2170
 
            mp4state.decode_pos_ms = mp4state.seek_needed;
2171
 
            mp4state.seek_needed = -1;
2172
 
        }
2173
 
 
2174
 
        if (done)
2175
 
        {
2176
 
            module.outMod->CanWrite();
2177
 
 
2178
 
            if (!module.outMod->IsPlaying())
2179
 
            {
2180
 
                PostMessage(module.hMainWindow, WM_WA_AAC_EOF, 0, 0);
2181
 
                PlayThreadAlive = 0;
2182
 
                return 0;
2183
 
            }
2184
 
 
2185
 
            Sleep(10);
2186
 
        } else if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short))) {
2187
 
 
2188
 
            if (mp4state.last_frame)
2189
 
            {
2190
 
                done = 1;
2191
 
            } else {
2192
 
                int rc;
2193
 
 
2194
 
                /* for gapless decoding */
2195
 
                char *buf;
2196
 
                long dur;
2197
 
                unsigned int sample_count;
2198
 
                unsigned int delay = 0;
2199
 
 
2200
 
                /* get acces unit from MP4 file */
2201
 
                buffer = NULL;
2202
 
                buffer_size = 0;
2203
 
 
2204
 
                dur = mp4ff_get_sample_duration(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId);
2205
 
                rc = mp4ff_read_sample(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId++, &buffer,  &buffer_size);
2206
 
 
2207
 
                if (mp4state.sampleId == 1) dur = 0;
2208
 
                if (rc == 0 || buffer == NULL)
2209
 
                {
2210
 
                    mp4state.last_frame = 1;
2211
 
                    sample_buffer = NULL;
2212
 
                    frameInfo.samples = 0;
2213
 
                } else {
2214
 
                    sample_buffer = NeAACDecDecode(mp4state.hDecoder, &frameInfo,
2215
 
                        buffer, buffer_size);
2216
 
                }
2217
 
                if (frameInfo.error > 0)
2218
 
                {
2219
 
                    show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
2220
 
                    mp4state.last_frame = 1;
2221
 
                }
2222
 
                if (mp4state.sampleId >= mp4state.numSamples)
2223
 
                    mp4state.last_frame = 1;
2224
 
 
2225
 
                if (buffer) free(buffer);
2226
 
 
2227
 
                if (mp4state.useAacLength || (mp4state.timescale != mp4state.samplerate)) {
2228
 
                    sample_count = frameInfo.samples;
2229
 
                } else {
2230
 
                    sample_count = (unsigned int)(dur * frameInfo.channels);
2231
 
 
2232
 
                    if (!mp4state.useAacLength && !mp4state.initial && (mp4state.sampleId < mp4state.numSamples/2) && (dur*frameInfo.channels != frameInfo.samples))
2233
 
                    {
2234
 
                        //fprintf(stderr, "MP4 seems to have incorrect frame duration, using values from AAC data.\n");
2235
 
                        mp4state.useAacLength = 1;
2236
 
                        sample_count = frameInfo.samples;
2237
 
                    }
2238
 
                }
2239
 
 
2240
 
                if (mp4state.initial && (sample_count < mp4state.framesize*mp4state.channels) && (frameInfo.samples > sample_count))
2241
 
                {
2242
 
                    delay = frameInfo.samples - sample_count;
2243
 
                }
2244
 
 
2245
 
                if (!killPlayThread && (sample_count > 0))
2246
 
                {
2247
 
                    buf = (char *)sample_buffer;
2248
 
                    mp4state.initial = 0;
2249
 
 
2250
 
                    switch (res_table[m_resolution])
2251
 
                    {
2252
 
                    case 8:
2253
 
                        buf += delay;
2254
 
                        break;
2255
 
                    case 16:
2256
 
                    default:
2257
 
                        buf += delay * 2;
2258
 
                        break;
2259
 
                    case 24:
2260
 
                    case 32:
2261
 
                        buf += delay * 4;
2262
 
                        break;
2263
 
                    case 64:
2264
 
                        buf += delay * 8;
2265
 
                    }
2266
 
 
2267
 
                    if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
2268
 
                        remap_channels(buf, sample_count, res_table[m_resolution]);
2269
 
 
2270
 
                    if (res_table[m_resolution] == 24)
2271
 
                    {
2272
 
                        /* convert libfaad output (3 bytes packed in 4) */
2273
 
                        char *temp_buffer = convert3in4to3in3(buf, sample_count);
2274
 
                        memcpy((void*)buf, (void*)temp_buffer, sample_count*3);
2275
 
                        free(temp_buffer);
2276
 
                    }
2277
 
 
2278
 
                    module.SAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
2279
 
                        mp4state.decode_pos_ms);
2280
 
                    module.VSAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
2281
 
                        mp4state.decode_pos_ms);
2282
 
                    mp4state.decode_pos_ms += (double)sample_count * 1000.0 /
2283
 
                        ((double)frameInfo.samplerate * (double)frameInfo.channels);
2284
 
 
2285
 
                    l = sample_count * res_table[m_resolution] / 8;
2286
 
 
2287
 
                    if (module.dsp_isactive())
2288
 
                    {
2289
 
                        void *dsp_buffer = malloc(l*2);
2290
 
                        memcpy(dsp_buffer, buf, l);
2291
 
 
2292
 
                        l = module.dsp_dosamples((short*)dsp_buffer,
2293
 
                            sample_count/frameInfo.channels,
2294
 
                            res_table[m_resolution],
2295
 
                            frameInfo.channels,
2296
 
                            frameInfo.samplerate) *
2297
 
                            (frameInfo.channels*(res_table[m_resolution]/8));
2298
 
 
2299
 
                        module.outMod->Write(dsp_buffer, l);
2300
 
                        if (dsp_buffer) free(dsp_buffer);
2301
 
                    } else {
2302
 
                        module.outMod->Write(buf, l);
2303
 
                    }
2304
 
 
2305
 
                    /* VBR bitrate display */
2306
 
                    if (m_vbr_display)
2307
 
                    {
2308
 
                        seq_frames++;
2309
 
                        seq_bytes += frameInfo.bytesconsumed;
2310
 
                        if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(sample_count/frameInfo.channels) + 0.5)))
2311
 
                        {
2312
 
                            module.SetInfo((int)floor(((float)seq_bytes*8.)/1000. + 0.5),
2313
 
                                (int)floor(frameInfo.samplerate/1000. + 0.5),
2314
 
                                mp4state.channels, 1);
2315
 
 
2316
 
                            seq_frames = 0;
2317
 
                            seq_bytes = 0;
2318
 
                        }
2319
 
                    }
2320
 
                }
2321
 
            }
2322
 
        } else {
2323
 
            Sleep(10);
2324
 
        }
2325
 
    }
2326
 
 
2327
 
    PlayThreadAlive = 0;
2328
 
 
2329
 
    return 0;
2330
 
}
2331
 
 
2332
 
void *decode_aac_frame(state *st, NeAACDecFrameInfo *frameInfo)
2333
 
{
2334
 
    void *sample_buffer = NULL;
2335
 
 
2336
 
    do
2337
 
    {
2338
 
        fill_buffer(st);
2339
 
 
2340
 
        if (st->m_aac_bytes_into_buffer != 0)
2341
 
        {
2342
 
            sample_buffer = NeAACDecDecode(st->hDecoder, frameInfo,
2343
 
                st->m_aac_buffer, st->m_aac_bytes_into_buffer);
2344
 
 
2345
 
            if (st->m_header_type != 1)
2346
 
            {
2347
 
                if (st->last_offset < st->m_file_offset)
2348
 
                {
2349
 
                    st->m_tail->offset = st->m_file_offset;
2350
 
                    st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
2351
 
                    st->m_tail = st->m_tail->next;
2352
 
                    st->m_tail->next = NULL;
2353
 
                    st->last_offset = st->m_file_offset;
2354
 
                }
2355
 
            }
2356
 
 
2357
 
            advance_buffer(st, frameInfo->bytesconsumed);
2358
 
        } else {
2359
 
            break;
2360
 
        }
2361
 
 
2362
 
    } while (!frameInfo->samples && !frameInfo->error);
2363
 
 
2364
 
    return sample_buffer;
2365
 
}
2366
 
 
2367
 
int aac_seek(state *st, double seconds)
2368
 
{
2369
 
    int i, frames;
2370
 
    int bread;
2371
 
    struct seek_list *target = st->m_head;
2372
 
 
2373
 
    if (1 /*can_seek*/ && ((st->m_header_type == 1) || (seconds < st->cur_pos_sec)))
2374
 
    {
2375
 
        frames = (int)(seconds*((double)st->samplerate/(double)st->framesize) + 0.5);
2376
 
 
2377
 
        for (i = 0; i < frames; i++)
2378
 
        {
2379
 
            if (target->next)
2380
 
                target = target->next;
2381
 
            else
2382
 
                return 0;
2383
 
        }
2384
 
        if (target->offset == 0 && frames > 0)
2385
 
            return 0;
2386
 
        fseek(st->aacfile, target->offset, SEEK_SET);
2387
 
        st->m_file_offset = target->offset;
2388
 
 
2389
 
        bread = fread(st->m_aac_buffer, 1, 768*6, st->aacfile);
2390
 
        if (bread != 768*6)
2391
 
            st->m_at_eof = 1;
2392
 
        else
2393
 
            st->m_at_eof = 0;
2394
 
        st->m_aac_bytes_into_buffer = bread;
2395
 
        st->m_aac_bytes_consumed = 0;
2396
 
        st->m_file_offset += bread;
2397
 
 
2398
 
        NeAACDecPostSeekReset(st->hDecoder, -1);
2399
 
 
2400
 
        return 1;
2401
 
    } else {
2402
 
        if (seconds > st->cur_pos_sec)
2403
 
        {
2404
 
            NeAACDecFrameInfo frameInfo;
2405
 
 
2406
 
            frames = (int)((seconds - st->cur_pos_sec)*((double)st->samplerate/(double)st->framesize));
2407
 
 
2408
 
            if (frames > 0)
2409
 
            {
2410
 
                for (i = 0; i < frames; i++)
2411
 
                {
2412
 
                    memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
2413
 
                    decode_aac_frame(st, &frameInfo);
2414
 
 
2415
 
                    if (frameInfo.error || (st->m_aac_bytes_into_buffer == 0))
2416
 
                    {
2417
 
                        if (frameInfo.error)
2418
 
                        {
2419
 
                            if (NeAACDecGetErrorMessage(frameInfo.error) != NULL)
2420
 
                                show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
2421
 
                        }
2422
 
                        return 0;
2423
 
                    }
2424
 
                }
2425
 
            }
2426
 
 
2427
 
            NeAACDecPostSeekReset(st->hDecoder, -1);
2428
 
        }
2429
 
        return 1;
2430
 
    }
2431
 
}
2432
 
 
2433
 
DWORD WINAPI AACPlayThread(void *b)
2434
 
{
2435
 
    int done = 0;
2436
 
    int l;
2437
 
    int seq_frames = 0;
2438
 
    int seq_bytes = 0;
2439
 
 
2440
 
#ifdef DEBUG_OUTPUT
2441
 
    in_mp4_DebugOutput("AACPlayThread");
2442
 
#endif
2443
 
 
2444
 
    PlayThreadAlive = 1;
2445
 
    mp4state.last_frame = 0;
2446
 
 
2447
 
    while (!*((int *)b))
2448
 
    {
2449
 
        /* seeking */
2450
 
        if (mp4state.seek_needed != -1)
2451
 
        {
2452
 
            double ms;
2453
 
 
2454
 
            ms = mp4state.seek_needed/1000;
2455
 
            if (aac_seek(&mp4state, ms)!=0)
2456
 
            {
2457
 
                module.outMod->Flush(mp4state.decode_pos_ms);
2458
 
                mp4state.cur_pos_sec = ms;
2459
 
                mp4state.decode_pos_ms = mp4state.seek_needed;
2460
 
            }
2461
 
            mp4state.seek_needed = -1;
2462
 
        }
2463
 
 
2464
 
        if (done)
2465
 
        {
2466
 
            module.outMod->CanWrite();
2467
 
 
2468
 
            if (!module.outMod->IsPlaying())
2469
 
            {
2470
 
                PostMessage(module.hMainWindow, WM_WA_AAC_EOF, 0, 0);
2471
 
                PlayThreadAlive = 0;
2472
 
                return 0;
2473
 
            }
2474
 
 
2475
 
            Sleep(10);
2476
 
        } else if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short))) {
2477
 
            NeAACDecFrameInfo frameInfo;
2478
 
            void *sample_buffer;
2479
 
 
2480
 
            memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
2481
 
 
2482
 
            sample_buffer = decode_aac_frame(&mp4state, &frameInfo);
2483
 
 
2484
 
            if (frameInfo.error || (mp4state.m_aac_bytes_into_buffer == 0))
2485
 
            {
2486
 
                if (frameInfo.error)
2487
 
                {
2488
 
                    if (NeAACDecGetErrorMessage(frameInfo.error) != NULL)
2489
 
                        show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
2490
 
                }
2491
 
                done = 1;
2492
 
            }
2493
 
 
2494
 
            if (!killPlayThread && (frameInfo.samples > 0))
2495
 
            {
2496
 
                if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
2497
 
                    remap_channels(sample_buffer, frameInfo.samples, res_table[m_resolution]);
2498
 
 
2499
 
                if (res_table[m_resolution] == 24)
2500
 
                {
2501
 
                    /* convert libfaad output (3 bytes packed in 4 bytes) */
2502
 
                    char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
2503
 
                    memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
2504
 
                    free(temp_buffer);
2505
 
                }
2506
 
 
2507
 
                module.SAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
2508
 
                    mp4state.decode_pos_ms);
2509
 
                module.VSAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
2510
 
                    mp4state.decode_pos_ms);
2511
 
                mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
2512
 
                    ((double)frameInfo.samplerate* (double)frameInfo.channels);
2513
 
 
2514
 
                l = frameInfo.samples * res_table[m_resolution] / 8;
2515
 
 
2516
 
                if (module.dsp_isactive())
2517
 
                {
2518
 
                    void *dsp_buffer = malloc(l*2);
2519
 
                    memcpy(dsp_buffer, sample_buffer, l);
2520
 
 
2521
 
                    l = module.dsp_dosamples((short*)dsp_buffer,
2522
 
                        frameInfo.samples/frameInfo.channels,
2523
 
                        res_table[m_resolution],
2524
 
                        frameInfo.channels,
2525
 
                        frameInfo.samplerate) *
2526
 
                        (frameInfo.channels*(res_table[m_resolution]/8));
2527
 
 
2528
 
                    module.outMod->Write(dsp_buffer, l);
2529
 
                    if (dsp_buffer) free(dsp_buffer);
2530
 
                } else {
2531
 
                    module.outMod->Write(sample_buffer, l);
2532
 
                }
2533
 
 
2534
 
                /* VBR bitrate display */
2535
 
                if (m_vbr_display)
2536
 
                {
2537
 
                    seq_frames++;
2538
 
                    seq_bytes += frameInfo.bytesconsumed;
2539
 
                    if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(frameInfo.samples/frameInfo.channels) + 0.5)))
2540
 
                    {
2541
 
                        module.SetInfo((int)floor(((float)seq_bytes*8.)/1000. + 0.5),
2542
 
                            (int)floor(frameInfo.samplerate/1000. + 0.5),
2543
 
                            mp4state.channels, 1);
2544
 
 
2545
 
                        seq_frames = 0;
2546
 
                        seq_bytes = 0;
2547
 
                    }
2548
 
                }
2549
 
            }
2550
 
 
2551
 
            if (frameInfo.channels > 0 && mp4state.samplerate > 0)
2552
 
                mp4state.cur_pos_sec += ((double)(frameInfo.samples/frameInfo.channels))/(double)mp4state.samplerate;
2553
 
        } else {
2554
 
            Sleep(10);
2555
 
        }
2556
 
    }
2557
 
 
2558
 
    PlayThreadAlive = 0;
2559
 
 
2560
 
    return 0;
2561
 
}
2562
 
 
2563
 
static In_Module module =
2564
 
{
2565
 
    IN_VER,
2566
 
    "AudioCoding.com MPEG-4 AAC player: " FAAD2_VERSION " compiled on " __DATE__,
2567
 
    0,  // hMainWindow
2568
 
    0,  // hDllInstance
2569
 
    NULL,
2570
 
    1, // is_seekable
2571
 
    1, // uses output
2572
 
    config,
2573
 
    about,
2574
 
    init,
2575
 
    quit,
2576
 
    getfileinfo,
2577
 
    infoDlg,
2578
 
    isourfile,
2579
 
    play,
2580
 
    pause,
2581
 
    unpause,
2582
 
    ispaused,
2583
 
    stop,
2584
 
 
2585
 
    getlength,
2586
 
    getoutputtime,
2587
 
    setoutputtime,
2588
 
 
2589
 
    setvolume,
2590
 
    setpan,
2591
 
 
2592
 
    0,0,0,0,0,0,0,0,0, // vis stuff
2593
 
 
2594
 
 
2595
 
    0,0, // dsp
2596
 
 
2597
 
    eq_set,
2598
 
 
2599
 
    NULL,       // setinfo
2600
 
 
2601
 
    0 // out_mod
2602
 
};
2603
 
 
2604
 
__declspec(dllexport) In_Module* winampGetInModule2()
2605
 
{
2606
 
    config_read();
2607
 
 
2608
 
    if (!m_use_for_aac)
2609
 
    {
2610
 
        module.FileExtensions = short_ext_list;
2611
 
    } else {
2612
 
        module.FileExtensions = long_ext_list;
2613
 
    }
2614
 
 
2615
 
    return &module;
2616
 
}
2617
 
 
2618
 
/* new Media Library interface */
2619
 
 
2620
 
int mp4_get_metadata(mp4ff_t *file, const char *item, char *dest, int dlen)
2621
 
{
2622
 
    char *pVal = NULL, dummy1[4096];
2623
 
 
2624
 
    if (dlen < 1) return 0;
2625
 
 
2626
 
    if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
2627
 
    {
2628
 
        if (mp4ff_meta_get_track(file, &pVal))
2629
 
        {
2630
 
            wsprintf(dummy1, "%s", pVal);
2631
 
            strncpy(dest, dummy1, dlen-1);
2632
 
            dest[dlen-1] = '\0';
2633
 
            return 1;
2634
 
        }
2635
 
    }
2636
 
    else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
2637
 
    {
2638
 
        if (mp4ff_meta_get_disc(file, &pVal))
2639
 
        {
2640
 
            wsprintf(dummy1, "%s", pVal);
2641
 
            strncpy(dest, dummy1, dlen-1);
2642
 
            dest[dlen-1] = '\0';
2643
 
            return 1;
2644
 
        }
2645
 
    }
2646
 
    else if (!stricmp(item, "compilation"))
2647
 
    {
2648
 
        uint8_t cpil = 0;
2649
 
        if (mp4ff_meta_get_compilation(file, &pVal))
2650
 
        {
2651
 
            wsprintf(dummy1, "%s", pVal);
2652
 
            strncpy(dest, dummy1, dlen-1);
2653
 
            dest[dlen-1] = '\0';
2654
 
            return 1;
2655
 
        }
2656
 
    }
2657
 
    else if (!stricmp(item, "tempo"))
2658
 
    {
2659
 
        if (mp4ff_meta_get_tempo(file, &pVal))
2660
 
        {
2661
 
            wsprintf(dummy1, "%s", pVal);
2662
 
            strncpy(dest, dummy1, dlen-1);
2663
 
            dest[dlen-1] = '\0';
2664
 
            return 1;
2665
 
        }
2666
 
    }
2667
 
    else if (!stricmp(item, "artist"))
2668
 
    {
2669
 
        if (mp4ff_meta_get_artist(file, &pVal))
2670
 
        {
2671
 
            strncpy(dest, pVal, dlen-1);
2672
 
            dest[dlen-1] = '\0';
2673
 
            return 1;
2674
 
        }
2675
 
    }
2676
 
    else if (!stricmp(item, "writer"))
2677
 
    {
2678
 
        if (mp4ff_meta_get_writer(file, &pVal))
2679
 
        {
2680
 
            strncpy(dest, pVal, dlen-1);
2681
 
            dest[dlen-1] = '\0';
2682
 
            return 1;
2683
 
        }
2684
 
    }
2685
 
    else if (!stricmp(item, "title"))
2686
 
    {
2687
 
        if (mp4ff_meta_get_title(file, &pVal))
2688
 
        {
2689
 
            strncpy(dest, pVal, dlen-1);
2690
 
            dest[dlen-1] = '\0';
2691
 
            return 1;
2692
 
        }
2693
 
    }
2694
 
    else if (!stricmp(item, "album"))
2695
 
    {
2696
 
        if (mp4ff_meta_get_album(file, &pVal))
2697
 
        {
2698
 
            strncpy(dest, pVal, dlen-1);
2699
 
            dest[dlen-1] = '\0';
2700
 
            return 1;
2701
 
        }
2702
 
    }
2703
 
    else if (!stricmp(item, "date") || !stricmp(item, "year"))
2704
 
    {
2705
 
        if (mp4ff_meta_get_date(file, &pVal))
2706
 
        {
2707
 
            strncpy(dest, pVal, dlen-1);
2708
 
            dest[dlen-1] = '\0';
2709
 
            return 1;
2710
 
        }
2711
 
    }
2712
 
    else if (!stricmp(item, "comment"))
2713
 
    {
2714
 
        if (mp4ff_meta_get_comment(file, &pVal))
2715
 
        {
2716
 
            strncpy(dest, pVal, dlen-1);
2717
 
            dest[dlen-1] = '\0';
2718
 
            return 1;
2719
 
        }
2720
 
    }
2721
 
    else if (!stricmp(item, "genre"))
2722
 
    {
2723
 
        if (mp4ff_meta_get_genre(file, &pVal))
2724
 
        {
2725
 
            strncpy(dest, pVal, dlen-1);
2726
 
            dest[dlen-1] = '\0';
2727
 
            return 1;
2728
 
        }
2729
 
    }
2730
 
    else if (!stricmp(item, "tool"))
2731
 
    {
2732
 
        if (mp4ff_meta_get_tool(file, &pVal))
2733
 
        {
2734
 
            strncpy(dest, pVal, dlen-1);
2735
 
            dest[dlen-1] = '\0';
2736
 
            return 1;
2737
 
        }
2738
 
    }
2739
 
#if 0
2740
 
    else
2741
 
    {
2742
 
        uint32_t valueSize = 0;
2743
 
        uint8_t *pValue = NULL;
2744
 
 
2745
 
        if (MP4GetMetadataFreeForm(file, (char *)item, &pValue, &valueSize))
2746
 
        {
2747
 
            unsigned int len = (valueSize < (unsigned int)(dlen-1)) ? valueSize : (unsigned int)(dlen-1);
2748
 
            memcpy(dest, pValue, len);
2749
 
            dest[len] = '\0';
2750
 
            return 1;
2751
 
        }
2752
 
    }
2753
 
#endif
2754
 
 
2755
 
    return 0;
2756
 
}
2757
 
 
2758
 
__declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *data, char *dest, int destlen)
2759
 
{
2760
 
    if (!fn || (fn && !*fn) || !destlen) return 0;
2761
 
 
2762
 
    dest[0] = '\0';
2763
 
 
2764
 
    if (!stricmp(data, "length"))
2765
 
    {
2766
 
        char temp[32];
2767
 
        int len = getsonglength(fn);
2768
 
        itoa(len, temp, 10);
2769
 
        strncpy(dest, temp, destlen-1);
2770
 
        dest[destlen-1] = '\0';
2771
 
    }
2772
 
    else
2773
 
    {
2774
 
        char temp[2048], temp2[2048];
2775
 
        FILE *mp4File;
2776
 
        mp4ff_callback_t mp4cb = {0};
2777
 
        mp4ff_t *file;
2778
 
 
2779
 
        mp4File = fopen(fn, "rb");
2780
 
        mp4cb.read = read_callback;
2781
 
        mp4cb.seek = seek_callback;
2782
 
        mp4cb.write = write_callback;
2783
 
        mp4cb.truncate = truncate_callback;
2784
 
        mp4cb.user_data = mp4File;
2785
 
 
2786
 
 
2787
 
        file = mp4ff_open_read(&mp4cb);
2788
 
        if (file == NULL) return 0;
2789
 
 
2790
 
        if (mp4_get_metadata(file, data, temp, sizeof(temp)))
2791
 
        {
2792
 
            int len = ConvertUTF8ToANSI(temp, temp2);
2793
 
            if (len > destlen-1) len = destlen-1;
2794
 
            memcpy(dest, temp2, len);
2795
 
            dest[len] = '\0';
2796
 
        }
2797
 
 
2798
 
        mp4ff_close(file);
2799
 
        fclose(mp4File);
2800
 
    }
2801
 
 
2802
 
    return 1;
2803
 
}
2804
 
 
2805
 
static mp4ff_metadata_t mltags = {0, 0};
2806
 
static BOOL medialib_init = FALSE;
2807
 
static char medialib_lastfn[2048] = "";
2808
 
 
2809
 
__declspec(dllexport) int winampSetExtendedFileInfo(const char *fn, const char *data, char *val)
2810
 
{
2811
 
    int len, ret = 0;
2812
 
    char *temp;
2813
 
 
2814
 
    if (!medialib_init || (medialib_init && stricmp(fn, medialib_lastfn))) {
2815
 
        FILE *mp4File;
2816
 
        mp4ff_callback_t mp4cb = {0};
2817
 
        mp4ff_t *file;
2818
 
        strcpy(medialib_lastfn, fn);
2819
 
 
2820
 
        if (medialib_init) tag_delete(&mltags);
2821
 
 
2822
 
        mp4File = fopen(medialib_lastfn, "rb");
2823
 
        mp4cb.read = read_callback;
2824
 
        mp4cb.seek = seek_callback;
2825
 
        mp4cb.user_data = mp4File;
2826
 
 
2827
 
 
2828
 
        file = mp4ff_open_read(&mp4cb);
2829
 
        if (file == NULL) return 0;
2830
 
 
2831
 
        ReadMP4Tag(file, &mltags);
2832
 
 
2833
 
        mp4ff_close(file);
2834
 
        fclose(mp4File);
2835
 
 
2836
 
        medialib_init = TRUE;
2837
 
    }
2838
 
 
2839
 
    len = strlen(val);
2840
 
    temp = (char *)malloc((len+1)*4);
2841
 
    if (!temp) return 0;
2842
 
 
2843
 
    if (ConvertANSIToUTF8(val, temp))
2844
 
    {
2845
 
        ret = 1;
2846
 
        tag_set_field(&mltags, data, temp, len);
2847
 
    }
2848
 
 
2849
 
    free(temp);
2850
 
 
2851
 
    return ret;
2852
 
}    
2853
 
 
2854
 
__declspec(dllexport) int winampWriteExtendedFileInfo()
2855
 
{
2856
 
    if (medialib_init)
2857
 
    {
2858
 
        FILE *mp4File;
2859
 
        mp4ff_callback_t mp4cb = {0};
2860
 
 
2861
 
        mp4File = fopen(medialib_lastfn, "rb+");
2862
 
        mp4cb.read = read_callback;
2863
 
        mp4cb.seek = seek_callback;
2864
 
        mp4cb.write = write_callback;
2865
 
        mp4cb.truncate = truncate_callback;
2866
 
        mp4cb.user_data = mp4File;
2867
 
 
2868
 
        mp4ff_meta_update(&mp4cb, &mltags);
2869
 
 
2870
 
        fclose(mp4File);
2871
 
 
2872
 
        return 1;
2873
 
    }
2874
 
    else
2875
 
    {
2876
 
        return 0;
2877
 
    }
2878
 
}
 
1
/*
 
2
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
 
3
** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
 
4
**  
 
5
** This program is free software; you can redistribute it and/or modify
 
6
** it under the terms of the GNU General Public License as published by
 
7
** the Free Software Foundation; either version 2 of the License, or
 
8
** (at your option) any later version.
 
9
** 
 
10
** This program is distributed in the hope that it will be useful,
 
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
** GNU General Public License for more details.
 
14
** 
 
15
** You should have received a copy of the GNU General Public License
 
16
** along with this program; if not, write to the Free Software 
 
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
**
 
19
** Any non-GPL usage of this software or parts of this software is strictly
 
20
** forbidden.
 
21
**
 
22
** Commercial non-GPL licensing of this software is possible.
 
23
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 
24
**
 
25
** $Id: in_mp4.c,v 1.56 2004/10/19 18:02:10 menno Exp $
 
26
**/
 
27
 
 
28
//#define DEBUG_OUTPUT
 
29
 
 
30
#define WIN32_LEAN_AND_MEAN
 
31
#include <windows.h>
 
32
#include <commctrl.h>
 
33
#include <commdlg.h>
 
34
#include <stdlib.h>
 
35
#include <stdio.h>
 
36
#include <io.h>
 
37
#include <math.h>
 
38
#include <neaacdec.h>
 
39
#define USE_TAGGING
 
40
#include <mp4ff.h>
 
41
 
 
42
#include "resource.h"
 
43
#include "in2.h"
 
44
#include "utils.h"
 
45
#include "config.h"
 
46
#include "aacinfo.h"
 
47
 
 
48
const char *long_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0AAC\0AAC Files (*.AAC)\0";
 
49
const char *short_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0";
 
50
 
 
51
static long priority_table[] = {
 
52
    0,
 
53
    THREAD_PRIORITY_HIGHEST,
 
54
    THREAD_PRIORITY_ABOVE_NORMAL,
 
55
    THREAD_PRIORITY_NORMAL,
 
56
    THREAD_PRIORITY_BELOW_NORMAL,
 
57
    THREAD_PRIORITY_LOWEST
 
58
};
 
59
static int res_id_table[] = {
 
60
    IDC_16BITS,
 
61
    IDC_24BITS,
 
62
    IDC_32BITS,
 
63
    0,
 
64
    0,
 
65
    /*IDC_16BITS_DITHERED*/ IDC_16BITS /* temp hack */
 
66
};
 
67
static int res_table[] = {
 
68
    16,
 
69
    24,
 
70
    32,
 
71
    0,
 
72
    0,
 
73
    16
 
74
};
 
75
static char info_fn[_MAX_PATH];
 
76
 
 
77
// post this to the main window at end of file (after playback has stopped)
 
78
#define WM_WA_AAC_EOF WM_USER+2
 
79
 
 
80
struct seek_list
 
81
{
 
82
    struct seek_list *next;
 
83
    __int64 offset;
 
84
};
 
85
 
 
86
typedef struct state
 
87
{
 
88
    /* general stuff */
 
89
    NeAACDecHandle hDecoder;
 
90
    int samplerate;
 
91
    unsigned char channels;
 
92
    double decode_pos_ms; // current decoding position, in milliseconds
 
93
    int paused; // are we paused?
 
94
    int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
 
95
    char filename[_MAX_PATH];
 
96
    int filetype; /* 0: MP4; 1: AAC */
 
97
    int last_frame;
 
98
    __int64 last_offset;
 
99
 
 
100
    /* MP4 stuff */
 
101
    mp4ff_t *mp4file;
 
102
    int mp4track;
 
103
    long numSamples;
 
104
    long sampleId;
 
105
    mp4ff_callback_t mp4cb;
 
106
    FILE *mp4File;
 
107
 
 
108
    /* AAC stuff */
 
109
    FILE *aacfile;
 
110
    long m_aac_bytes_into_buffer;
 
111
    long m_aac_bytes_consumed;
 
112
    __int64 m_file_offset;
 
113
    unsigned char *m_aac_buffer;
 
114
    int m_at_eof;
 
115
    double cur_pos_sec;
 
116
    int m_header_type;
 
117
    struct seek_list *m_head;
 
118
    struct seek_list *m_tail;
 
119
    unsigned long m_length;
 
120
 
 
121
    /* for gapless decoding */
 
122
    unsigned int useAacLength;
 
123
    unsigned int framesize;
 
124
    unsigned int initial;
 
125
    unsigned long timescale;
 
126
} state;
 
127
 
 
128
static state mp4state;
 
129
 
 
130
static In_Module module; // the output module (declared near the bottom of this file)
 
131
 
 
132
static int killPlayThread;
 
133
static int PlayThreadAlive = 0; // 1=play thread still running
 
134
HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
 
135
 
 
136
/* Function definitions */
 
137
void *decode_aac_frame(state *st, NeAACDecFrameInfo *frameInfo);
 
138
DWORD WINAPI MP4PlayThread(void *b); // the decode thread procedure
 
139
DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure
 
140
 
 
141
 
 
142
uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
 
143
{
 
144
    return fread(buffer, 1, length, (FILE*)user_data);
 
145
}
 
146
 
 
147
uint32_t seek_callback(void *user_data, uint64_t position)
 
148
{
 
149
    return fseek((FILE*)user_data, position, SEEK_SET);
 
150
}
 
151
 
 
152
uint32_t write_callback(void *user_data, void *buffer, uint32_t length)
 
153
{
 
154
    return fwrite(buffer, 1, length, (FILE*)user_data);
 
155
}
 
156
 
 
157
uint32_t truncate_callback(void *user_data)
 
158
{
 
159
    _chsize(fileno((FILE*)user_data), ftell((FILE*)user_data));
 
160
    return 1;
 
161
}
 
162
 
 
163
 
 
164
int tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
 
165
{
 
166
    void *backup = (void *)tags->tags;
 
167
 
 
168
    if (!item || (item && !*item) || !value) return 0;
 
169
 
 
170
    tags->tags = (mp4ff_tag_t *)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
 
171
    if (!tags->tags) {
 
172
        if (backup) free(backup);
 
173
        return 0;
 
174
    }
 
175
    else
 
176
    {
 
177
        size_t i_len = strlen(item);
 
178
        if (v_len == 0) v_len = strlen(value);
 
179
 
 
180
        tags->tags[tags->count].item = (char *)malloc(i_len+1);
 
181
        tags->tags[tags->count].value = (char *)malloc(v_len+1);
 
182
 
 
183
        if (!tags->tags[tags->count].item || !tags->tags[tags->count].value)
 
184
        {
 
185
            if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item);
 
186
            if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value);
 
187
            tags->tags[tags->count].item = NULL;
 
188
            tags->tags[tags->count].value = NULL;
 
189
            return 0;
 
190
        }
 
191
 
 
192
        memcpy(tags->tags[tags->count].item, item, i_len);
 
193
        memcpy(tags->tags[tags->count].value, value, v_len);
 
194
        tags->tags[tags->count].item[i_len] = '\0';
 
195
        tags->tags[tags->count].value[v_len] = '\0';
 
196
//        tags->tags[tags->count].len = v_len;
 
197
 
 
198
        tags->count++;
 
199
        return 1;
 
200
    }
 
201
}
 
202
 
 
203
int tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
 
204
{
 
205
    unsigned int i;
 
206
 
 
207
    if (!item || (item && !*item) || !value) return 0;
 
208
 
 
209
    for (i = 0; i < tags->count; i++)
 
210
    {
 
211
        if (!stricmp(tags->tags[i].item, item))
 
212
        {
 
213
            void *backup = (void *)tags->tags[i].value;
 
214
            if (v_len == 0) v_len = strlen(value);
 
215
 
 
216
            tags->tags[i].value = (char *)realloc(tags->tags[i].value, v_len+1);
 
217
            if (!tags->tags[i].value)
 
218
            {
 
219
                if (backup) free(backup);
 
220
                return 0;
 
221
            }
 
222
 
 
223
            memcpy(tags->tags[i].value, value, v_len);
 
224
            tags->tags[i].value[v_len] = '\0';
 
225
//            tags->tags[i].len = v_len;
 
226
 
 
227
            return 1;
 
228
        }
 
229
    }
 
230
 
 
231
    return tag_add_field(tags, item, value, v_len);
 
232
}
 
233
 
 
234
int tag_delete(mp4ff_metadata_t *tags)
 
235
{
 
236
    unsigned int i;
 
237
 
 
238
    for (i = 0; i < tags->count; i++)
 
239
    {
 
240
        if (tags->tags[i].item) free(tags->tags[i].item);
 
241
        if (tags->tags[i].value) free(tags->tags[i].value);
 
242
    }
 
243
 
 
244
    if (tags->tags) free(tags->tags);
 
245
 
 
246
    tags->tags = NULL;
 
247
    tags->count = 0;
 
248
}
 
249
 
 
250
int ReadMP4Tag(mp4ff_t *file, mp4ff_metadata_t *tags)
 
251
{
 
252
    unsigned __int8 *pValue;
 
253
    char *pName;
 
254
    unsigned int i = 0;
 
255
 
 
256
    do {
 
257
        pName = 0;
 
258
        pValue = 0;
 
259
 
 
260
 
 
261
        if (mp4ff_meta_get_by_index(file, i, (char **)&pName, &pValue))
 
262
        {
 
263
            char *val = (char *)strdup(pValue);
 
264
            if (!val) return 0;
 
265
 
 
266
            if (pName[0] == 'ļæ½')
 
267
            {
 
268
                if (memcmp(pName, "ļæ½nam", 4) == 0)
 
269
                {
 
270
                    tag_add_field(tags, "title", val, strlen(val));
 
271
                } else if (memcmp(pName, "ļæ½ART", 4) == 0) {
 
272
                    tag_add_field(tags, "artist", val, strlen(val));
 
273
                } else if (memcmp(pName, "ļæ½wrt", 4) == 0) {
 
274
                    tag_add_field(tags, "writer", val, strlen(val));
 
275
                } else if (memcmp(pName, "ļæ½alb", 4) == 0) {
 
276
                    tag_add_field(tags, "album", val, strlen(val));
 
277
                } else if (memcmp(pName, "ļæ½day", 4) == 0) {
 
278
                    tag_add_field(tags, "date", val, strlen(val));
 
279
                } else if (memcmp(pName, "ļæ½too", 4) == 0) {
 
280
                    tag_add_field(tags, "tool", val, strlen(val));
 
281
                } else if (memcmp(pName, "ļæ½cmt", 4) == 0) {
 
282
                    tag_add_field(tags, "comment", val, strlen(val));
 
283
                } else if (memcmp(pName, "ļæ½gen", 4) == 0) {
 
284
                    tag_add_field(tags, "genre", val, strlen(val));
 
285
                } else {
 
286
                    tag_add_field(tags, pName, val, strlen(val));
 
287
                }
 
288
            } else if (memcmp(pName, "covr", 4) == 0) {
 
289
                tag_add_field(tags, "cover", val, strlen(val));
 
290
            } else if (memcmp(pName, "gnre", 4) == 0) {
 
291
                tag_add_field(tags, "genre", val, strlen(val));
 
292
            } else if (memcmp(pName, "trkn", 4) == 0) {
 
293
                tag_add_field(tags, "tracknumber", val, strlen(val));
 
294
            } else if (memcmp(pName, "disk", 4) == 0) {
 
295
                tag_add_field(tags, "disc", val, strlen(val));
 
296
            } else if (memcmp(pName, "cpil", 4) == 0) {
 
297
                tag_add_field(tags, "compilation", val, strlen(val));
 
298
            } else if (memcmp(pName, "tmpo", 4) == 0) {
 
299
                tag_add_field(tags, "tempo", val, strlen(val));
 
300
            } else if (memcmp(pName, "NDFL", 4) == 0) {
 
301
                /* Removed */
 
302
            } else {
 
303
                tag_add_field(tags, pName, val, strlen(val));
 
304
            }
 
305
 
 
306
            free(val);
 
307
        }
 
308
 
 
309
        i++;
 
310
    } while (pValue != NULL);
 
311
 
 
312
    return 1;
 
313
}
 
314
 
 
315
 
 
316
#ifdef DEBUG_OUTPUT
 
317
void in_mp4_DebugOutput(char *message)
 
318
{
 
319
    char s[1024];
 
320
 
 
321
    sprintf(s, "in_mp4: %s", message);
 
322
    OutputDebugString(s);
 
323
}
 
324
#endif
 
325
 
 
326
int file_length(FILE *f)
 
327
{
 
328
    long end = 0;
 
329
    long cur = ftell(f);
 
330
    fseek(f, 0, SEEK_END);
 
331
    end = ftell(f);
 
332
    fseek(f, cur, SEEK_SET);
 
333
 
 
334
    return end;
 
335
}
 
336
 
 
337
static void show_error(HWND hwnd, char *message, ...)
 
338
{
 
339
    if (m_show_errors)
 
340
        MessageBox(hwnd, message, "Error", MB_OK);
 
341
}
 
342
 
 
343
static void config_init()
 
344
{
 
345
    char *p=INI_FILE;
 
346
    GetModuleFileName(NULL,INI_FILE,_MAX_PATH);
 
347
    while (*p) p++;
 
348
    while (p >= INI_FILE && *p != '.') p--;
 
349
    strcpy(p+1,"ini");
 
350
}
 
351
 
 
352
void config_read()
 
353
{
 
354
    char priority[10];
 
355
    char resolution[10];
 
356
    char show_errors[10];
 
357
    char use_for_aac[10];
 
358
    char downmix[10];
 
359
    char vbr_display[10];
 
360
 
 
361
    config_init();
 
362
 
 
363
    strcpy(show_errors, "1");
 
364
    strcpy(priority, "3");
 
365
    strcpy(resolution, "0");
 
366
    strcpy(use_for_aac, "1");
 
367
    strcpy(downmix, "0");
 
368
    strcpy(vbr_display, "1");
 
369
    strcpy(titleformat, "%7");
 
370
 
 
371
    RS(priority);
 
372
    RS(resolution);
 
373
    RS(show_errors);
 
374
    RS(use_for_aac);
 
375
    RS(downmix);
 
376
    RS(vbr_display);
 
377
    RS(titleformat);
 
378
 
 
379
    m_priority = atoi(priority);
 
380
    m_resolution = atoi(resolution);
 
381
    m_show_errors = atoi(show_errors);
 
382
    m_use_for_aac = atoi(use_for_aac);
 
383
    m_downmix = atoi(downmix);
 
384
    m_vbr_display = atoi(vbr_display);
 
385
}
 
386
 
 
387
void config_write()
 
388
{
 
389
    char priority[10];
 
390
    char resolution[10];
 
391
    char show_errors[10];
 
392
    char use_for_aac[10];
 
393
    char downmix[10];
 
394
    char vbr_display[10];
 
395
 
 
396
    itoa(m_priority, priority, 10);
 
397
    itoa(m_resolution, resolution, 10);
 
398
    itoa(m_show_errors, show_errors, 10);
 
399
    itoa(m_use_for_aac, use_for_aac, 10);
 
400
    itoa(m_downmix, downmix, 10);
 
401
    itoa(m_vbr_display, vbr_display, 10);
 
402
 
 
403
    WS(priority);
 
404
    WS(resolution);
 
405
    WS(show_errors);
 
406
    WS(use_for_aac);
 
407
    WS(downmix);
 
408
    WS(vbr_display);
 
409
    WS(titleformat);
 
410
}
 
411
 
 
412
void init()
 
413
{
 
414
    config_read();
 
415
}
 
416
 
 
417
void quit()
 
418
{
 
419
}
 
420
 
 
421
/* Convert UNICODE to UTF-8
 
422
   Return number of bytes written */
 
423
int unicodeToUtf8 ( const WCHAR* lpWideCharStr, char* lpMultiByteStr, int cwcChars )
 
424
{
 
425
    const unsigned short*   pwc = (unsigned short *)lpWideCharStr;
 
426
    unsigned char*          pmb = (unsigned char  *)lpMultiByteStr;
 
427
    const unsigned short*   pwce;
 
428
    size_t  cBytes = 0;
 
429
 
 
430
    if ( cwcChars >= 0 ) {
 
431
        pwce = pwc + cwcChars;
 
432
    } else {
 
433
        pwce = (unsigned short *)((size_t)-1);
 
434
    }
 
435
 
 
436
    while ( pwc < pwce ) {
 
437
        unsigned short  wc = *pwc++;
 
438
 
 
439
        if ( wc < 0x00000080 ) {
 
440
            *pmb++ = (char)wc;
 
441
            cBytes++;
 
442
        } else
 
443
        if ( wc < 0x00000800 ) {
 
444
            *pmb++ = (char)(0xC0 | ((wc >>  6) & 0x1F));
 
445
            cBytes++;
 
446
            *pmb++ = (char)(0x80 |  (wc        & 0x3F));
 
447
            cBytes++;
 
448
        } else
 
449
        if ( wc < 0x00010000 ) {
 
450
            *pmb++ = (char)(0xE0 | ((wc >> 12) & 0x0F));
 
451
            cBytes++;
 
452
            *pmb++ = (char)(0x80 | ((wc >>  6) & 0x3F));
 
453
            cBytes++;
 
454
            *pmb++ = (char)(0x80 |  (wc        & 0x3F));
 
455
            cBytes++;
 
456
        }
 
457
        if ( wc == L'\0' )
 
458
            return cBytes;
 
459
    }
 
460
 
 
461
    return cBytes;
 
462
}
 
463
 
 
464
/* Convert UTF-8 coded string to UNICODE
 
465
   Return number of characters converted */
 
466
int utf8ToUnicode ( const char* lpMultiByteStr, WCHAR* lpWideCharStr, int cmbChars )
 
467
{
 
468
    const unsigned char*    pmb = (unsigned char  *)lpMultiByteStr;
 
469
    unsigned short*         pwc = (unsigned short *)lpWideCharStr;
 
470
    const unsigned char*    pmbe;
 
471
    size_t  cwChars = 0;
 
472
 
 
473
    if ( cmbChars >= 0 ) {
 
474
        pmbe = pmb + cmbChars;
 
475
    } else {
 
476
        pmbe = (unsigned char *)((size_t)-1);
 
477
    }
 
478
 
 
479
    while ( pmb < pmbe ) {
 
480
        char            mb = *pmb++;
 
481
        unsigned int    cc = 0;
 
482
        unsigned int    wc;
 
483
 
 
484
        while ( (cc < 7) && (mb & (1 << (7 - cc)))) {
 
485
            cc++;
 
486
        }
 
487
 
 
488
        if ( cc == 1 || cc > 6 )                    // illegal character combination for UTF-8
 
489
            continue;
 
490
 
 
491
        if ( cc == 0 ) {
 
492
            wc = mb;
 
493
        } else {
 
494
            wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6);
 
495
            while ( --cc > 0 ) {
 
496
                if ( pmb == pmbe )                  // reached end of the buffer
 
497
                    return cwChars;
 
498
                mb = *pmb++;
 
499
                if ( ((mb >> 6) & 0x03) != 2 )      // not part of multibyte character
 
500
                    return cwChars;
 
501
                wc |= (mb & 0x3F) << ((cc - 1) * 6);
 
502
            }
 
503
        }
 
504
 
 
505
        if ( wc & 0xFFFF0000 )
 
506
            wc = L'?';
 
507
        *pwc++ = wc;
 
508
        cwChars++;
 
509
        if ( wc == L'\0' )
 
510
            return cwChars;
 
511
    }
 
512
 
 
513
    return cwChars;
 
514
}
 
515
 
 
516
/* convert Windows ANSI to UTF-8 */
 
517
int ConvertANSIToUTF8 ( const char* ansi, char* utf8 )
 
518
{
 
519
    WCHAR*  wszValue;          // Unicode value
 
520
    size_t  ansi_len;
 
521
    size_t  len;
 
522
 
 
523
    *utf8 = '\0';
 
524
    if ( ansi == NULL )
 
525
        return 0;
 
526
 
 
527
    ansi_len = strlen ( ansi );
 
528
 
 
529
    if ( (wszValue = (WCHAR *)malloc ( (ansi_len + 1) * 2 )) == NULL )
 
530
        return 0;
 
531
 
 
532
    /* Convert ANSI value to Unicode */
 
533
    if ( (len = MultiByteToWideChar ( CP_ACP, 0, ansi, ansi_len + 1, wszValue, (ansi_len + 1) * 2 )) == 0 ) {
 
534
        free ( wszValue );
 
535
        return 0;
 
536
    }
 
537
 
 
538
    /* Convert Unicode value to UTF-8 */
 
539
    if ( (len = unicodeToUtf8 ( wszValue, utf8, -1 )) == 0 ) {
 
540
        free ( wszValue );
 
541
        return 0;
 
542
    }
 
543
 
 
544
    free ( wszValue );
 
545
 
 
546
    return len-1;
 
547
}
 
548
 
 
549
/* convert UTF-8 to Windows ANSI */
 
550
int ConvertUTF8ToANSI ( const char* utf8, char* ansi )
 
551
{
 
552
    WCHAR*  wszValue;          // Unicode value
 
553
    size_t  utf8_len;
 
554
    size_t  len;
 
555
 
 
556
    *ansi = '\0';
 
557
    if ( utf8 == NULL )
 
558
        return 0;
 
559
 
 
560
    utf8_len = strlen ( utf8 );
 
561
 
 
562
    if ( (wszValue = (WCHAR *)malloc ( (utf8_len + 1) * 2 )) == NULL )
 
563
        return 0;
 
564
 
 
565
    /* Convert UTF-8 value to Unicode */
 
566
    if ( (len = utf8ToUnicode ( utf8, wszValue, utf8_len + 1 )) == 0 ) {
 
567
        free ( wszValue );
 
568
        return 0;
 
569
    }
 
570
 
 
571
    /* Convert Unicode value to ANSI */
 
572
    if ( (len = WideCharToMultiByte ( CP_ACP, 0, wszValue, -1, ansi, (utf8_len + 1) * 2, NULL, NULL )) == 0 ) {
 
573
        free ( wszValue );
 
574
        return 0;
 
575
    }
 
576
 
 
577
    free ( wszValue );
 
578
 
 
579
    return len-1;
 
580
}
 
581
 
 
582
BOOL uSetDlgItemText(HWND hwnd, int id, const char *str)
 
583
{
 
584
    char *temp;
 
585
    size_t len;
 
586
    int r;
 
587
 
 
588
    if (!str) return FALSE;
 
589
    if (!*str) return TRUE;
 
590
    len = strlen(str);
 
591
    temp = malloc(len+1);
 
592
    if (!temp) return FALSE;
 
593
    r = ConvertUTF8ToANSI(str, temp);
 
594
    if (r > 0)
 
595
        SetDlgItemText(hwnd, id, temp);
 
596
    free(temp);
 
597
 
 
598
    return r>0 ? TRUE : FALSE;
 
599
}
 
600
 
 
601
UINT uGetDlgItemText(HWND hwnd, int id, char *str, int max)
 
602
{
 
603
    char *temp, *utf8;
 
604
    int len;
 
605
    HWND w;
 
606
 
 
607
    if (!str || !max) return 0;
 
608
    *str = '\0';
 
609
    w = GetDlgItem(hwnd, id);
 
610
    len = GetWindowTextLength(w);
 
611
    temp = malloc(len+1);
 
612
    if (!temp) return 0;
 
613
    utf8 = malloc((len+1)*4);
 
614
    if (!utf8)
 
615
    {
 
616
        free(temp);
 
617
        return 0;
 
618
    }
 
619
 
 
620
    len = GetWindowText(w, temp, len+1);
 
621
    if (len > 0)
 
622
    {
 
623
        len = ConvertANSIToUTF8(temp, utf8);
 
624
        if (len > max-1)
 
625
        {
 
626
            len = max-1;
 
627
            utf8[max] = '\0';
 
628
        }
 
629
        memcpy(str, utf8, len+1);
 
630
    }
 
631
 
 
632
    free(temp);
 
633
    free(utf8);
 
634
 
 
635
    return len;
 
636
}
 
637
 
 
638
static void mp4fileinfo(mp4ff_t *mp4, char *info, size_t len)
 
639
{
 
640
    char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
 
641
    long samples;
 
642
    float f = 1024.0;
 
643
    float seconds;
 
644
    int track;
 
645
 
 
646
    NeAACDecHandle hDecoder;
 
647
    NeAACDecFrameInfo frameInfo;
 
648
    mp4AudioSpecificConfig mp4ASC = {0};
 
649
    unsigned char *buffer = NULL;
 
650
    int buffer_size = 0;
 
651
    unsigned long sr = 0;
 
652
    unsigned char ch = 0;
 
653
 
 
654
    if ((track = GetAACTrack(mp4)) < 0)
 
655
    {
 
656
        info[0] = '\0';
 
657
        return;
 
658
    }
 
659
 
 
660
    hDecoder = NeAACDecOpen();
 
661
 
 
662
    samples = mp4ff_num_samples(mp4, track);
 
663
 
 
664
    mp4ff_get_decoder_config(mp4, track, &buffer, &buffer_size);
 
665
    if (buffer)
 
666
    {
 
667
        if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
 
668
        {
 
669
            if (mp4ASC.frameLengthFlag == 1) f = 960.0;
 
670
            if (mp4ASC.sbr_present_flag == 1) f *= 2;
 
671
        }
 
672
 
 
673
        if(NeAACDecInit2(hDecoder, buffer, buffer_size, &sr, &ch) < 0)
 
674
        {
 
675
            /* If some error initializing occured, skip the file */
 
676
            free(buffer);
 
677
            return;
 
678
        }
 
679
 
 
680
        free(buffer);
 
681
        buffer = NULL;
 
682
    }
 
683
 
 
684
    if (mp4ff_read_sample(mp4, track, 0, &buffer,  &buffer_size) == 0)
 
685
    {
 
686
        return;
 
687
    }
 
688
    NeAACDecDecode(hDecoder, &frameInfo, buffer, buffer_size);
 
689
 
 
690
    if (buffer) free(buffer);
 
691
 
 
692
    seconds = (float)samples*(float)(f-1.0)/(float)mp4ASC.samplingFrequency;
 
693
 
 
694
    wsprintf(info, "MPEG-4 %s, %d.%d secs, %d ch, %d Hz\nSBR: %s\nParametric stereo: %s",
 
695
        ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
 
696
        (int)(seconds),
 
697
        (int)(seconds*1000.0 + 0.5) % 1000,
 
698
        mp4ASC.channelsConfiguration,
 
699
        mp4ASC.samplingFrequency,
 
700
        /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
 
701
        (frameInfo.sbr == 0) ? "off" : ((frameInfo.sbr == 1) ? "on, normal" : ((frameInfo.sbr == 2) ? "on, downsampled" : "off, upsampled")),
 
702
        (frameInfo.ps == 0) ? "no" : "yes");
 
703
 
 
704
    NeAACDecClose(hDecoder);
 
705
}
 
706
 
 
707
BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
 
708
                                   WPARAM wParam, LPARAM lParam)
 
709
{
 
710
    char file_info[1024];
 
711
    mp4ff_t *file;
 
712
    FILE *mp4File;
 
713
    mp4ff_callback_t mp4cb = {0};
 
714
    char *pVal;
 
715
    mp4ff_metadata_t tags;
 
716
    char dummy1[1024];
 
717
    char temp[1024];
 
718
    int dummy, dummy2, dummy3;
 
719
    tags.count = 0;
 
720
    tags.tags = NULL;
 
721
 
 
722
#ifdef DEBUG_OUTPUT
 
723
    in_mp4_DebugOutput("mp4_info_dialog_proc");
 
724
#endif
 
725
 
 
726
    switch (message) {
 
727
    case WM_INITDIALOG:
 
728
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT), FALSE);
 
729
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT), SW_HIDE);
 
730
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), FALSE);
 
731
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), SW_HIDE);
 
732
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), FALSE);
 
733
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), SW_HIDE);
 
734
 
 
735
        mp4File = fopen(info_fn, "rb");
 
736
        mp4cb.read = read_callback;
 
737
        mp4cb.seek = seek_callback;
 
738
        mp4cb.user_data = mp4File;
 
739
 
 
740
 
 
741
        file = mp4ff_open_read(&mp4cb);
 
742
        if (file == NULL)
 
743
            return FALSE;
 
744
 
 
745
        mp4fileinfo(file, file_info, 1024);
 
746
        SetDlgItemText(hwndDlg, IDC_INFOTEXT, file_info);
 
747
 
 
748
        /* get Metadata */
 
749
 
 
750
        pVal = NULL;
 
751
        if (mp4ff_meta_get_title(file, &pVal))
 
752
            uSetDlgItemText(hwndDlg,IDC_METANAME, pVal);
 
753
 
 
754
        pVal = NULL;
 
755
        if (mp4ff_meta_get_artist(file, &pVal))
 
756
            uSetDlgItemText(hwndDlg,IDC_METAARTIST, pVal);
 
757
 
 
758
        pVal = NULL;
 
759
        if (mp4ff_meta_get_writer(file, &pVal))
 
760
            uSetDlgItemText(hwndDlg,IDC_METAWRITER, pVal);
 
761
 
 
762
        pVal = NULL;
 
763
        if (mp4ff_meta_get_comment(file, &pVal))
 
764
            uSetDlgItemText(hwndDlg,IDC_METACOMMENTS, pVal);
 
765
 
 
766
        pVal = NULL;
 
767
        if (mp4ff_meta_get_album(file, &pVal))
 
768
            uSetDlgItemText(hwndDlg,IDC_METAALBUM, pVal);
 
769
 
 
770
        pVal = NULL;
 
771
        if (mp4ff_meta_get_genre(file, &pVal))
 
772
            uSetDlgItemText(hwndDlg,IDC_METAGENRE, pVal);
 
773
 
 
774
        pVal = NULL;
 
775
        if (mp4ff_meta_get_track(file, &pVal))
 
776
        {
 
777
            SetDlgItemText(hwndDlg,IDC_METATRACK1, pVal);
 
778
 
 
779
            //pVal = NULL;
 
780
            //mp4ff_meta_get_totaltracks(file, &pVal);
 
781
            //SetDlgItemText(hwndDlg, IDC_METATRACK2, pVal);
 
782
        }
 
783
 
 
784
        pVal = NULL;
 
785
        if (mp4ff_meta_get_disc(file, &pVal))
 
786
        {
 
787
            SetDlgItemText(hwndDlg,IDC_METADISK1, pVal);
 
788
 
 
789
            //pVal = NULL;
 
790
            //mp4ff_meta_get_totaldiscs(file, &pVal);
 
791
            //SetDlgItemText(hwndDlg,IDC_METADISK2, pVal);
 
792
        }
 
793
 
 
794
        pVal = NULL;
 
795
        if (mp4ff_meta_get_date(file, &pVal))
 
796
            uSetDlgItemText(hwndDlg,IDC_METAYEAR, pVal);
 
797
 
 
798
#if 0
 
799
        /* WERKT NIET */
 
800
#endif
 
801
        pVal = NULL;
 
802
        if (mp4ff_meta_get_compilation(file, &pVal))
 
803
        {
 
804
            if (strcmp(pVal, "1") == 0)
 
805
            {
 
806
                SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
 
807
            }
 
808
        }
 
809
 
 
810
        /* ! Metadata */
 
811
 
 
812
        mp4ff_close(file);
 
813
        fclose(mp4File);
 
814
 
 
815
        return TRUE;
 
816
 
 
817
    case WM_COMMAND:
 
818
        switch (LOWORD(wParam)) {
 
819
        case IDCANCEL:
 
820
            EndDialog(hwndDlg, wParam);
 
821
            return TRUE;
 
822
        case IDOK:
 
823
 
 
824
            /* trying to edit currently playing file */
 
825
 
 
826
            if (!stricmp(info_fn, mp4state.filename))
 
827
            {
 
828
                MessageBox(module.hMainWindow, "Please stop playback before editing tags", "in_mp4", MB_ICONINFORMATION|MB_OK);
 
829
                return TRUE;
 
830
            }
 
831
 
 
832
            /* save Metadata changes */
 
833
 
 
834
            tag_delete(&tags);
 
835
 
 
836
            mp4File = fopen(info_fn, "rb");
 
837
            mp4cb.read = read_callback;
 
838
            mp4cb.seek = seek_callback;
 
839
            mp4cb.write = write_callback;
 
840
            mp4cb.truncate = truncate_callback;
 
841
            mp4cb.user_data = mp4File;
 
842
 
 
843
 
 
844
            file = mp4ff_open_read(&mp4cb);
 
845
            if (file != NULL)
 
846
            {
 
847
                ReadMP4Tag(file, &tags);
 
848
                mp4ff_close(file);
 
849
                fclose(mp4File);
 
850
            }
 
851
 
 
852
            mp4File = fopen(info_fn, "rb+");
 
853
            mp4cb.read = read_callback;
 
854
            mp4cb.seek = seek_callback;
 
855
            mp4cb.write = write_callback;
 
856
            mp4cb.truncate = truncate_callback;
 
857
            mp4cb.user_data = mp4File;
 
858
 
 
859
 
 
860
            uGetDlgItemText(hwndDlg, IDC_METANAME, dummy1, 1024);
 
861
            tag_set_field(&tags, "title", dummy1, strlen(dummy1));
 
862
 
 
863
            uGetDlgItemText(hwndDlg, IDC_METAWRITER, dummy1, 1024);
 
864
            tag_set_field(&tags, "writer", dummy1, strlen(dummy1));
 
865
 
 
866
            uGetDlgItemText(hwndDlg, IDC_METAARTIST, dummy1, 1024);
 
867
            tag_set_field(&tags, "artist", dummy1, strlen(dummy1));
 
868
 
 
869
            uGetDlgItemText(hwndDlg, IDC_METAALBUM, dummy1, 1024);
 
870
            tag_set_field(&tags, "album", dummy1, strlen(dummy1));
 
871
 
 
872
            uGetDlgItemText(hwndDlg, IDC_METACOMMENTS, dummy1, 1024);
 
873
            tag_set_field(&tags, "comment", dummy1, strlen(dummy1));
 
874
 
 
875
            uGetDlgItemText(hwndDlg, IDC_METAGENRE, dummy1, 1024);
 
876
            tag_set_field(&tags, "genre", dummy1, strlen(dummy1));
 
877
 
 
878
            uGetDlgItemText(hwndDlg, IDC_METAYEAR, dummy1, 1024);
 
879
            tag_set_field(&tags, "year", dummy1, strlen(dummy1));
 
880
 
 
881
            GetDlgItemText(hwndDlg, IDC_METATRACK1, dummy1, 1024);
 
882
            dummy = atoi(dummy1);
 
883
            //GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
 
884
            //dummy2 = atoi(dummy1);
 
885
            //wsprintf(temp, "%d/%d", dummy, dummy2);
 
886
            wsprintf(temp, "%d", dummy);
 
887
            tag_set_field(&tags, "track", temp, strlen(dummy1));
 
888
 
 
889
            GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024);
 
890
            dummy = atoi(dummy1);
 
891
            //GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
 
892
            //dummy2 = atoi(dummy1);
 
893
            //wsprintf(temp, "%d/%d", dummy, dummy2);
 
894
            wsprintf(temp, "%d", dummy);
 
895
            tag_set_field(&tags, "disc", temp, strlen(dummy1));
 
896
 
 
897
            dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0);
 
898
            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 1);
 
899
 
 
900
            mp4ff_meta_update(&mp4cb, &tags);
 
901
 
 
902
            fclose(mp4File);
 
903
 
 
904
            /* ! */
 
905
 
 
906
            EndDialog(hwndDlg, wParam);
 
907
            return TRUE;
 
908
        }
 
909
    }
 
910
    return FALSE;
 
911
}
 
912
 
 
913
/* returns the name of the object type */
 
914
char *get_ot_string(int ot)
 
915
{
 
916
    switch (ot)
 
917
    {
 
918
    case 0:
 
919
        return "Main";
 
920
    case 1:
 
921
        return "LC";
 
922
    case 2:
 
923
        return "SSR";
 
924
    case 3:
 
925
        return "LTP";
 
926
    }
 
927
    return NULL;
 
928
}
 
929
 
 
930
BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
 
931
                                   WPARAM wParam, LPARAM lParam)
 
932
{
 
933
    faadAACInfo aacInfo;
 
934
    char *info_text, *header_string;
 
935
 
 
936
#ifdef DEBUG_OUTPUT
 
937
    in_mp4_DebugOutput("aac_info_dialog_proc");
 
938
#endif
 
939
 
 
940
    switch (message) {
 
941
    case WM_INITDIALOG:
 
942
        EnableWindow(GetDlgItem(hwndDlg,IDC_USERDATA), FALSE) ;
 
943
        ShowWindow(GetDlgItem(hwndDlg,IDC_USERDATA), SW_HIDE);
 
944
 
 
945
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC1), SW_HIDE);
 
946
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC2), SW_HIDE);
 
947
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC3), SW_HIDE);
 
948
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC4), SW_HIDE);
 
949
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC5), SW_HIDE);
 
950
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC6), SW_HIDE);
 
951
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC7), SW_HIDE);
 
952
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC8), SW_HIDE);
 
953
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC9), SW_HIDE);
 
954
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC10), SW_HIDE);
 
955
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC11), SW_HIDE);
 
956
        ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC12), SW_HIDE);
 
957
 
 
958
        ShowWindow(GetDlgItem(hwndDlg,IDC_METANAME), SW_HIDE);
 
959
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAARTIST), SW_HIDE);
 
960
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAWRITER), SW_HIDE);
 
961
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMMENTS), SW_HIDE);
 
962
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAALBUM), SW_HIDE);
 
963
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAGENRE), SW_HIDE);
 
964
        ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK1), SW_HIDE);
 
965
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
 
966
        ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK1), SW_HIDE);
 
967
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
 
968
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAYEAR), SW_HIDE);
 
969
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMPILATION), SW_HIDE);
 
970
 
 
971
        info_text = malloc(1024*sizeof(char));
 
972
 
 
973
        get_AAC_format(info_fn, &aacInfo);
 
974
 
 
975
        switch (aacInfo.headertype)
 
976
        {
 
977
        case 0: /* RAW */
 
978
            header_string = " RAW";
 
979
            break;
 
980
        case 1: /* ADIF */
 
981
            header_string = " ADIF";
 
982
            break;
 
983
        case 2: /* ADTS */
 
984
            header_string = " ADTS";
 
985
            break;
 
986
        }
 
987
 
 
988
        sprintf(info_text, "%s AAC %s%s, %d sec, %d kbps, %d Hz",
 
989
            (aacInfo.version==2)?"MPEG-2":"MPEG-4", get_ot_string(aacInfo.object_type),
 
990
            header_string,
 
991
            (int)((float)aacInfo.length/1000.0), (int)((float)aacInfo.bitrate/1000.0+0.5),
 
992
            aacInfo.sampling_rate);
 
993
 
 
994
        SetDlgItemText(hwndDlg, IDC_INFOTEXT, info_text);
 
995
 
 
996
        free(info_text);
 
997
 
 
998
        return TRUE;
 
999
 
 
1000
    case WM_COMMAND:
 
1001
        switch (LOWORD(wParam))
 
1002
        {
 
1003
        case IDCANCEL:
 
1004
        case IDOK:
 
1005
            EndDialog(hwndDlg, wParam);
 
1006
            return TRUE;
 
1007
        }
 
1008
    }
 
1009
    return FALSE;
 
1010
}
 
1011
 
 
1012
int infoDlg(char *fn, HWND hwndParent)
 
1013
{
 
1014
    if(!stricmp(fn + strlen(fn) - 3,"AAC"))
 
1015
    {
 
1016
        lstrcpy(info_fn, fn);
 
1017
 
 
1018
        DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
 
1019
            hwndParent, aac_info_dialog_proc);
 
1020
    } else {
 
1021
        lstrcpy(info_fn, fn);
 
1022
 
 
1023
        DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
 
1024
            hwndParent, mp4_info_dialog_proc);
 
1025
    }
 
1026
 
 
1027
    return 0;
 
1028
}
 
1029
 
 
1030
/* Get the title from the file */
 
1031
void ConstructTitle(mp4ff_t *file, char *filename, char *title, char *format)
 
1032
{
 
1033
    char temp[4096];
 
1034
    int some_info = 0;
 
1035
    char *in = format;
 
1036
    char *out = temp;//title;
 
1037
    char *bound = out + sizeof(temp) - 256; //out + (MAX_PATH - 10 - 1);
 
1038
    char *pVal, dummy1[1024];
 
1039
    short dummy, dummy2;
 
1040
 
 
1041
    while (*in && out < bound)
 
1042
    {
 
1043
        switch (*in)
 
1044
        {
 
1045
        case '%':
 
1046
            ++in;
 
1047
            break;
 
1048
 
 
1049
        default:
 
1050
            *out++ = *in++;
 
1051
            continue;
 
1052
        }
 
1053
 
 
1054
        /* handle % escape sequence */
 
1055
        switch (*in++)
 
1056
        {
 
1057
        case '0':
 
1058
            pVal = NULL;
 
1059
            if (mp4ff_meta_get_track(file, &pVal))
 
1060
            {
 
1061
                out += wsprintf(out, "%s", pVal);
 
1062
                some_info = 1;
 
1063
            }
 
1064
            break;
 
1065
 
 
1066
        case '1':
 
1067
            pVal = NULL;
 
1068
            if (mp4ff_meta_get_artist(file, &pVal))
 
1069
            {
 
1070
                out += wsprintf(out, "%s", pVal);
 
1071
                some_info = 1;
 
1072
            }
 
1073
            break;
 
1074
 
 
1075
        case '2':
 
1076
            pVal = NULL;
 
1077
            if (mp4ff_meta_get_title(file, &pVal))
 
1078
            {
 
1079
                out += wsprintf(out, "%s", pVal);
 
1080
                some_info = 1;
 
1081
            }
 
1082
            break;
 
1083
 
 
1084
        case '3':
 
1085
            pVal = NULL;
 
1086
            if (mp4ff_meta_get_album(file, &pVal))
 
1087
            {
 
1088
                out += wsprintf(out, "%s", pVal);
 
1089
                some_info = 1;
 
1090
            }
 
1091
            break;
 
1092
 
 
1093
        case '4':
 
1094
            pVal = NULL;
 
1095
            if (mp4ff_meta_get_date(file, &pVal))
 
1096
            {
 
1097
                out += wsprintf(out, "%s", pVal);
 
1098
                some_info = 1;
 
1099
            }
 
1100
            break;
 
1101
 
 
1102
        case '5':
 
1103
            pVal = NULL;
 
1104
            if (mp4ff_meta_get_comment(file, &pVal))
 
1105
            {
 
1106
                out += wsprintf(out, "%s", pVal);
 
1107
                some_info = 1;
 
1108
            }
 
1109
            break;
 
1110
 
 
1111
        case '6':
 
1112
            pVal = NULL;
 
1113
            if (mp4ff_meta_get_genre(file, &pVal))
 
1114
            {
 
1115
                out += wsprintf(out, "%s", pVal);
 
1116
                some_info = 1;
 
1117
            }
 
1118
            break;
 
1119
 
 
1120
        case '7':
 
1121
            {
 
1122
                const char *p=strrchr(filename,'\\');
 
1123
                if (!p) p=filename; else p++;
 
1124
                out += ConvertANSIToUTF8(p, out);
 
1125
                some_info = 1;
 
1126
                break;
 
1127
            }
 
1128
 
 
1129
        default:
 
1130
            break;
 
1131
        }
 
1132
    }
 
1133
 
 
1134
    *out = '\0';
 
1135
 
 
1136
    if (!some_info)
 
1137
    {
 
1138
        char *p=filename+lstrlen(filename);
 
1139
        while (*p != '\\' && p >= filename) p--;
 
1140
        lstrcpy(title,++p);
 
1141
    }
 
1142
    else
 
1143
    {
 
1144
        int len = ConvertUTF8ToANSI(temp, dummy1);
 
1145
        if (len > (MAX_PATH - 10 - 1)) len = (MAX_PATH - 10 - 1);
 
1146
        memcpy(title, dummy1, len);
 
1147
        title[len] = '\0';
 
1148
    }
 
1149
}
 
1150
 
 
1151
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message,
 
1152
                                 WPARAM wParam, LPARAM lParam)
 
1153
{
 
1154
    int i;
 
1155
 
 
1156
    switch (message) {
 
1157
    case WM_INITDIALOG:
 
1158
        SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETRANGE, TRUE, MAKELONG(1,5));
 
1159
        SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETPOS, TRUE, m_priority);
 
1160
        SendMessage(GetDlgItem(hwndDlg, res_id_table[m_resolution]), BM_SETCHECK, BST_CHECKED, 0);
 
1161
        if (m_show_errors)
 
1162
            SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_SETCHECK, BST_CHECKED, 0);
 
1163
        if (m_use_for_aac)
 
1164
            SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_SETCHECK, BST_CHECKED, 0);
 
1165
        if (m_downmix)
 
1166
            SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_SETCHECK, BST_CHECKED, 0);
 
1167
        if (m_vbr_display)
 
1168
            SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_SETCHECK, BST_CHECKED, 0);
 
1169
        SetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat);
 
1170
        return TRUE;
 
1171
 
 
1172
    case WM_COMMAND:
 
1173
        switch (LOWORD(wParam)) {
 
1174
        case IDCANCEL:
 
1175
            EndDialog(hwndDlg, wParam);
 
1176
            return TRUE;
 
1177
        case IDOK:
 
1178
            m_show_errors = SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_GETCHECK, 0, 0);
 
1179
            m_use_for_aac = SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_GETCHECK, 0, 0);
 
1180
            m_downmix = SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_GETCHECK, 0, 0);
 
1181
            m_vbr_display = SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_GETCHECK, 0, 0);
 
1182
            GetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat, MAX_PATH);
 
1183
 
 
1184
            m_priority = SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_GETPOS, 0, 0);
 
1185
            for (i = 0; i < 6; i++)
 
1186
            {
 
1187
                if (SendMessage(GetDlgItem(hwndDlg, res_id_table[i]), BM_GETCHECK, 0, 0))
 
1188
                {
 
1189
                    m_resolution = i;
 
1190
                    break;
 
1191
                }
 
1192
            }
 
1193
 
 
1194
            /* save config */
 
1195
            config_write();
 
1196
 
 
1197
            if (!m_use_for_aac)
 
1198
            {
 
1199
                module.FileExtensions = short_ext_list;
 
1200
            } else {
 
1201
                module.FileExtensions = long_ext_list;
 
1202
            }
 
1203
 
 
1204
            EndDialog(hwndDlg, wParam);
 
1205
            return TRUE;
 
1206
        }
 
1207
    }
 
1208
    return FALSE;
 
1209
}
 
1210
 
 
1211
void config(HWND hwndParent)
 
1212
{
 
1213
    DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG),
 
1214
        hwndParent, config_dialog_proc);
 
1215
 
 
1216
    return;
 
1217
}
 
1218
 
 
1219
void about(HWND hwndParent)
 
1220
{
 
1221
    MessageBox(hwndParent,
 
1222
        "AudioCoding.com MPEG-4 AAC player " FAAD2_VERSION " compiled on " __DATE__ ".\n"
 
1223
        "Visit the website for more info.\n"
 
1224
        "Copyright 2002-2004 AudioCoding.com",
 
1225
        "About",
 
1226
        MB_OK);
 
1227
}
 
1228
 
 
1229
int isourfile(char *fn)
 
1230
{
 
1231
    if (!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
 
1232
    {
 
1233
        return 1;
 
1234
    } else if (m_use_for_aac) {
 
1235
        if (!stricmp(fn + strlen(fn) - 3,"AAC"))
 
1236
        {
 
1237
            return 1;
 
1238
        }
 
1239
    }
 
1240
 
 
1241
    return 0;
 
1242
}
 
1243
 
 
1244
int fill_buffer(state *st)
 
1245
{
 
1246
    int bread;
 
1247
 
 
1248
    if (st->m_aac_bytes_consumed > 0)
 
1249
    {
 
1250
        if (st->m_aac_bytes_into_buffer)
 
1251
        {
 
1252
            memmove((void*)st->m_aac_buffer, (void*)(st->m_aac_buffer + st->m_aac_bytes_consumed),
 
1253
                st->m_aac_bytes_into_buffer*sizeof(unsigned char));
 
1254
        }
 
1255
 
 
1256
        if (!st->m_at_eof)
 
1257
        {
 
1258
            bread = fread((void*)(st->m_aac_buffer + st->m_aac_bytes_into_buffer),
 
1259
                1, st->m_aac_bytes_consumed, st->aacfile);
 
1260
 
 
1261
            if (bread != st->m_aac_bytes_consumed)
 
1262
                st->m_at_eof = 1;
 
1263
 
 
1264
            st->m_aac_bytes_into_buffer += bread;
 
1265
        }
 
1266
 
 
1267
        st->m_aac_bytes_consumed = 0;
 
1268
 
 
1269
        if (st->m_aac_bytes_into_buffer > 3)
 
1270
        {
 
1271
            if (memcmp(st->m_aac_buffer, "TAG", 3) == 0)
 
1272
                st->m_aac_bytes_into_buffer = 0;
 
1273
        }
 
1274
        if (st->m_aac_bytes_into_buffer > 11)
 
1275
        {
 
1276
            if (memcmp(st->m_aac_buffer, "LYRICSBEGIN", 11) == 0)
 
1277
                st->m_aac_bytes_into_buffer = 0;
 
1278
        }
 
1279
        if (st->m_aac_bytes_into_buffer > 8)
 
1280
        {
 
1281
            if (memcmp(st->m_aac_buffer, "APETAGEX", 8) == 0)
 
1282
                st->m_aac_bytes_into_buffer = 0;
 
1283
        }
 
1284
    }
 
1285
 
 
1286
    return 1;
 
1287
}
 
1288
 
 
1289
void advance_buffer(state *st, int bytes)
 
1290
{
 
1291
    st->m_file_offset += bytes;
 
1292
    st->m_aac_bytes_consumed = bytes;
 
1293
    st->m_aac_bytes_into_buffer -= bytes;
 
1294
}
 
1295
 
 
1296
int adts_parse(state *st, __int64 *bitrate, double *length)
 
1297
{
 
1298
    static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
 
1299
    int frames, frame_length;
 
1300
    int t_framelength = 0;
 
1301
    int samplerate;
 
1302
    double frames_per_sec, bytes_per_frame;
 
1303
 
 
1304
    /* Read all frames to ensure correct time and bitrate */
 
1305
    for (frames = 0; /* */; frames++)
 
1306
    {
 
1307
        fill_buffer(st);
 
1308
 
 
1309
        if (st->m_aac_bytes_into_buffer > 7)
 
1310
        {
 
1311
            /* check syncword */
 
1312
            if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
 
1313
                break;
 
1314
 
 
1315
            st->m_tail->offset = st->m_file_offset;
 
1316
            st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
 
1317
            st->m_tail = st->m_tail->next;
 
1318
            st->m_tail->next = NULL;
 
1319
 
 
1320
            if (frames == 0)
 
1321
                samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];
 
1322
 
 
1323
            frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
 
1324
                | (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);
 
1325
 
 
1326
            t_framelength += frame_length;
 
1327
 
 
1328
            if (frame_length > st->m_aac_bytes_into_buffer)
 
1329
                break;
 
1330
 
 
1331
            advance_buffer(st, frame_length);
 
1332
        } else {
 
1333
            break;
 
1334
        }
 
1335
    }
 
1336
 
 
1337
    frames_per_sec = (double)samplerate/1024.0;
 
1338
    if (frames != 0)
 
1339
        bytes_per_frame = (double)t_framelength/(double)(frames*1000);
 
1340
    else
 
1341
        bytes_per_frame = 0;
 
1342
    *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
 
1343
    if (frames_per_sec != 0)
 
1344
        *length = (double)frames/frames_per_sec;
 
1345
    else
 
1346
        *length = 1;
 
1347
 
 
1348
    return 1;
 
1349
}
 
1350
 
 
1351
int skip_id3v2_tag()
 
1352
{
 
1353
    unsigned char buf[10];
 
1354
    int bread, tagsize = 0;
 
1355
 
 
1356
    bread = fread(buf, 1, 10, mp4state.aacfile);
 
1357
    if (bread != 10) return -1;
 
1358
 
 
1359
    if (!memcmp(buf, "ID3", 3))
 
1360
    {
 
1361
        /* high bit is not used */
 
1362
        tagsize = (buf[6] << 21) | (buf[7] << 14) | (buf[8] << 7) | (buf[9] << 0);
 
1363
 
 
1364
        tagsize += 10;
 
1365
        fseek(mp4state.aacfile, tagsize, SEEK_SET);
 
1366
    } else {
 
1367
        fseek(mp4state.aacfile, 0, SEEK_SET);
 
1368
    }
 
1369
 
 
1370
    return tagsize;
 
1371
}
 
1372
 
 
1373
int play(char *fn)
 
1374
{
 
1375
    int maxlatency;
 
1376
    int thread_id;
 
1377
    int avg_bitrate, br, sr;
 
1378
    unsigned char *buffer;
 
1379
    int buffer_size;
 
1380
    NeAACDecConfigurationPtr config;
 
1381
    unsigned char header[8];
 
1382
    FILE *hMP4File;
 
1383
 
 
1384
#ifdef DEBUG_OUTPUT
 
1385
    in_mp4_DebugOutput("play");
 
1386
#endif
 
1387
 
 
1388
    memset(&mp4state, 0, sizeof(state));
 
1389
 
 
1390
    lstrcpy(mp4state.filename, fn);
 
1391
 
 
1392
    hMP4File = fopen(mp4state.filename, "rb");
 
1393
    if (!hMP4File)
 
1394
    {
 
1395
        return -1;
 
1396
    }
 
1397
    fread(header, 1, 8, hMP4File);
 
1398
    fclose(hMP4File);
 
1399
    mp4state.filetype = 1;
 
1400
    if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
 
1401
        mp4state.filetype = 0;
 
1402
 
 
1403
    if (mp4state.filetype)
 
1404
    {
 
1405
        int tagsize = 0, tmp = 0, init;
 
1406
        int bread = 0;
 
1407
        double length = 0.;
 
1408
        __int64 bitrate = 128;
 
1409
//        NeAACDecFrameInfo frameInfo;
 
1410
 
 
1411
        module.is_seekable = 1;
 
1412
 
 
1413
        if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
 
1414
        {
 
1415
            // error
 
1416
            return -1;
 
1417
        }
 
1418
 
 
1419
        tagsize = skip_id3v2_tag();
 
1420
        if (tagsize<0) return 0;
 
1421
 
 
1422
        if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
 
1423
        {
 
1424
            show_error(module.hMainWindow, "Memory allocation error.");
 
1425
            return -1;
 
1426
        }
 
1427
 
 
1428
        for (init=0; init<2; init++)
 
1429
        {
 
1430
            mp4state.hDecoder = NeAACDecOpen();
 
1431
            if (!mp4state.hDecoder)
 
1432
            {
 
1433
                show_error(module.hMainWindow, "Unable to open decoder library.");
 
1434
                return -1;
 
1435
            }
 
1436
 
 
1437
            config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
 
1438
            config->outputFormat = m_resolution + 1;
 
1439
            config->downMatrix = m_downmix;
 
1440
            NeAACDecSetConfiguration(mp4state.hDecoder, config);
 
1441
 
 
1442
            memset(mp4state.m_aac_buffer, 0, 768*6);
 
1443
            bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
 
1444
            mp4state.m_aac_bytes_into_buffer = bread;
 
1445
            mp4state.m_aac_bytes_consumed = 0;
 
1446
            mp4state.m_file_offset = 0;
 
1447
            mp4state.m_at_eof = (bread != 768*6) ? 1 : 0;
 
1448
 
 
1449
            if (init==0)
 
1450
            {
 
1451
                NeAACDecFrameInfo frameInfo;
 
1452
 
 
1453
                fill_buffer(&mp4state);
 
1454
 
 
1455
                if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
 
1456
                    mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
 
1457
                    &mp4state.samplerate, &mp4state.channels)) < 0)
 
1458
                {
 
1459
                    show_error(module.hMainWindow, "Can't initialize decoder library.");
 
1460
                    return -1;
 
1461
                }
 
1462
                advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
 
1463
 
 
1464
                do {
 
1465
                    memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
 
1466
                    fill_buffer(&mp4state);
 
1467
                    NeAACDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
 
1468
                } while (!frameInfo.samples && !frameInfo.error);
 
1469
 
 
1470
                if (frameInfo.error)
 
1471
                {
 
1472
                    show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
 
1473
                    return -1;
 
1474
                }
 
1475
 
 
1476
                mp4state.channels = frameInfo.channels;
 
1477
                mp4state.samplerate = frameInfo.samplerate;
 
1478
                mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
 
1479
                /*
 
1480
                sbr = frameInfo.sbr;
 
1481
                profile = frameInfo.object_type;
 
1482
                header_type = frameInfo.header_type;
 
1483
                */
 
1484
 
 
1485
                NeAACDecClose(mp4state.hDecoder);
 
1486
                fseek(mp4state.aacfile, tagsize, SEEK_SET);
 
1487
            }
 
1488
        }
 
1489
 
 
1490
        mp4state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
 
1491
        mp4state.m_tail = mp4state.m_head;
 
1492
        mp4state.m_tail->next = NULL;
 
1493
 
 
1494
        mp4state.m_header_type = 0;
 
1495
        if ((mp4state.m_aac_buffer[0] == 0xFF) && ((mp4state.m_aac_buffer[1] & 0xF6) == 0xF0))
 
1496
        {
 
1497
            if (1) //(can_seek)
 
1498
            {
 
1499
                adts_parse(&mp4state, &bitrate, &length);
 
1500
                fseek(mp4state.aacfile, tagsize, SEEK_SET);
 
1501
 
 
1502
                bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
 
1503
                if (bread != 768*6)
 
1504
                    mp4state.m_at_eof = 1;
 
1505
                else
 
1506
                    mp4state.m_at_eof = 0;
 
1507
                mp4state.m_aac_bytes_into_buffer = bread;
 
1508
                mp4state.m_aac_bytes_consumed = 0;
 
1509
 
 
1510
                mp4state.m_header_type = 1;
 
1511
            }
 
1512
        } else if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0) {
 
1513
            int skip_size = (mp4state.m_aac_buffer[4] & 0x80) ? 9 : 0;
 
1514
            bitrate = ((unsigned int)(mp4state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
 
1515
                ((unsigned int)mp4state.m_aac_buffer[5 + skip_size]<<11) |
 
1516
                ((unsigned int)mp4state.m_aac_buffer[6 + skip_size]<<3) |
 
1517
                ((unsigned int)mp4state.m_aac_buffer[7 + skip_size] & 0xE0);
 
1518
 
 
1519
            length = (double)file_length(mp4state.aacfile);
 
1520
            if (length == -1)
 
1521
            {
 
1522
                module.is_seekable = 0;
 
1523
                length = 0;
 
1524
            } else {
 
1525
                length = ((double)length*8.)/((double)bitrate) + 0.5;
 
1526
            }
 
1527
 
 
1528
            mp4state.m_header_type = 2;
 
1529
        } else {
 
1530
            length = (double)file_length(mp4state.aacfile);
 
1531
            length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
 
1532
 
 
1533
            module.is_seekable = 1;
 
1534
        }
 
1535
 
 
1536
        mp4state.m_length = (int)(length*1000.);
 
1537
 
 
1538
        fill_buffer(&mp4state);
 
1539
        if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
 
1540
            mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
 
1541
            &mp4state.samplerate, &mp4state.channels)) < 0)
 
1542
        {
 
1543
            show_error(module.hMainWindow, "Can't initialize decoder library.");
 
1544
            return -1;
 
1545
        }
 
1546
        advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
 
1547
 
 
1548
        if (mp4state.m_header_type == 2)
 
1549
            avg_bitrate = bitrate;
 
1550
        else
 
1551
            avg_bitrate = bitrate*1000;
 
1552
    } else {
 
1553
        mp4state.hDecoder = NeAACDecOpen();
 
1554
        if (!mp4state.hDecoder)
 
1555
        {
 
1556
            show_error(module.hMainWindow, "Unable to open decoder library.");
 
1557
            return -1;
 
1558
        }
 
1559
 
 
1560
        config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
 
1561
        config->outputFormat = m_resolution + 1;
 
1562
        config->downMatrix = m_downmix;
 
1563
        NeAACDecSetConfiguration(mp4state.hDecoder, config);
 
1564
 
 
1565
        mp4state.mp4File = fopen(mp4state.filename, "rb");
 
1566
        mp4state.mp4cb.read = read_callback;
 
1567
        mp4state.mp4cb.seek = seek_callback;
 
1568
        mp4state.mp4cb.user_data = mp4state.mp4File;
 
1569
 
 
1570
 
 
1571
        mp4state.mp4file = mp4ff_open_read(&mp4state.mp4cb);
 
1572
        if (!mp4state.mp4file)
 
1573
        {
 
1574
            show_error(module.hMainWindow, "Unable to open file.");
 
1575
            NeAACDecClose(mp4state.hDecoder);
 
1576
            return -1;
 
1577
        }
 
1578
 
 
1579
        if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
 
1580
        {
 
1581
            show_error(module.hMainWindow, "Unsupported Audio track type.");
 
1582
            NeAACDecClose(mp4state.hDecoder);
 
1583
            mp4ff_close(mp4state.mp4file);
 
1584
            fclose(mp4state.mp4File);
 
1585
            return -1;
 
1586
        }
 
1587
 
 
1588
        buffer = NULL;
 
1589
        buffer_size = 0;
 
1590
        mp4ff_get_decoder_config(mp4state.mp4file, mp4state.mp4track,
 
1591
            &buffer, &buffer_size);
 
1592
        if (!buffer)
 
1593
        {
 
1594
            NeAACDecClose(mp4state.hDecoder);
 
1595
            mp4ff_close(mp4state.mp4file);
 
1596
            fclose(mp4state.mp4File);
 
1597
            return -1;
 
1598
        }
 
1599
 
 
1600
        if(NeAACDecInit2(mp4state.hDecoder, buffer, buffer_size,
 
1601
            &mp4state.samplerate, &mp4state.channels) < 0)
 
1602
        {
 
1603
            /* If some error initializing occured, skip the file */
 
1604
            NeAACDecClose(mp4state.hDecoder);
 
1605
            mp4ff_close(mp4state.mp4file);
 
1606
            fclose(mp4state.mp4File);
 
1607
            if (buffer) free (buffer);
 
1608
            return -1;
 
1609
        }
 
1610
 
 
1611
        /* for gapless decoding */
 
1612
        {
 
1613
            mp4AudioSpecificConfig mp4ASC;
 
1614
 
 
1615
            mp4state.timescale = mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
 
1616
            mp4state.framesize = 1024;
 
1617
            mp4state.useAacLength = 0;
 
1618
 
 
1619
            if (buffer)
 
1620
            {
 
1621
                if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
 
1622
                {
 
1623
                    if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
 
1624
                    if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
 
1625
                }
 
1626
            }
 
1627
        }
 
1628
 
 
1629
        free(buffer);
 
1630
 
 
1631
        avg_bitrate = mp4ff_get_avg_bitrate(mp4state.mp4file, mp4state.mp4track);
 
1632
 
 
1633
        mp4state.numSamples = mp4ff_num_samples(mp4state.mp4file, mp4state.mp4track);
 
1634
        mp4state.sampleId = 0;
 
1635
 
 
1636
        {
 
1637
            double timescale_div = 1.0 / (double)mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
 
1638
            int64_t duration = mp4ff_get_track_duration_use_offsets(mp4state.mp4file, mp4state.mp4track);
 
1639
            if (duration == -1)
 
1640
            {
 
1641
                mp4state.m_length = 0;
 
1642
            } else {
 
1643
                mp4state.m_length = (int)((double)duration * timescale_div * 1000.0);
 
1644
            }
 
1645
        }
 
1646
 
 
1647
        module.is_seekable = 1;
 
1648
    }
 
1649
 
 
1650
    if (mp4state.channels == 0)
 
1651
    {
 
1652
        show_error(module.hMainWindow, "Number of channels not supported for playback.");
 
1653
        NeAACDecClose(mp4state.hDecoder);
 
1654
        if (mp4state.filetype)
 
1655
            fclose(mp4state.aacfile);
 
1656
        else {
 
1657
            mp4ff_close(mp4state.mp4file);
 
1658
            fclose(mp4state.mp4File);
 
1659
        }
 
1660
        return -1;
 
1661
    }
 
1662
 
 
1663
    if (m_downmix && (mp4state.channels == 5 || mp4state.channels == 6))
 
1664
        mp4state.channels = 2;
 
1665
 
 
1666
    maxlatency = module.outMod->Open(mp4state.samplerate, (int)mp4state.channels,
 
1667
        res_table[m_resolution], -1, -1);
 
1668
 
 
1669
    if (maxlatency < 0) // error opening device
 
1670
    {
 
1671
        NeAACDecClose(mp4state.hDecoder);
 
1672
        if (mp4state.filetype)
 
1673
            fclose(mp4state.aacfile);
 
1674
        else {
 
1675
            mp4ff_close(mp4state.mp4file);
 
1676
            fclose(mp4state.mp4File);
 
1677
        }
 
1678
        return -1;
 
1679
    }
 
1680
 
 
1681
    mp4state.paused        =  0;
 
1682
    mp4state.decode_pos_ms =  0;
 
1683
    mp4state.seek_needed   = -1;
 
1684
 
 
1685
    // initialize vis stuff
 
1686
    module.SAVSAInit(maxlatency, mp4state.samplerate);
 
1687
    module.VSASetInfo((int)mp4state.channels, mp4state.samplerate);
 
1688
 
 
1689
    br = (int)floor(((float)avg_bitrate + 500.0)/1000.0 + 0.5);
 
1690
    sr = (int)floor((float)mp4state.samplerate/1000.0 + 0.5);
 
1691
    module.SetInfo(br, sr, (int)mp4state.channels, 1);
 
1692
 
 
1693
    module.outMod->SetVolume(-666); // set the output plug-ins default volume
 
1694
 
 
1695
    killPlayThread = 0;
 
1696
 
 
1697
    if (mp4state.filetype)
 
1698
    {
 
1699
        if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AACPlayThread,
 
1700
            (void *)&killPlayThread, 0, &thread_id)) == NULL)
 
1701
        {
 
1702
            show_error(module.hMainWindow, "Cannot create playback thread");
 
1703
            NeAACDecClose(mp4state.hDecoder);
 
1704
            fclose(mp4state.aacfile);
 
1705
            return -1;
 
1706
        }
 
1707
    } else {
 
1708
        if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MP4PlayThread,
 
1709
            (void *)&killPlayThread, 0, &thread_id)) == NULL)
 
1710
        {
 
1711
            show_error(module.hMainWindow, "Cannot create playback thread");
 
1712
            NeAACDecClose(mp4state.hDecoder);
 
1713
            mp4ff_close(mp4state.mp4file);
 
1714
            fclose(mp4state.mp4File);
 
1715
            return -1;
 
1716
        }
 
1717
    }
 
1718
 
 
1719
    SetThreadAffinityMask(play_thread_handle, 1);
 
1720
 
 
1721
    SetThreadPriority(play_thread_handle, priority_table[m_priority]);
 
1722
 
 
1723
    return 0;
 
1724
}
 
1725
 
 
1726
void pause()
 
1727
{
 
1728
#ifdef DEBUG_OUTPUT
 
1729
    in_mp4_DebugOutput("pause");
 
1730
#endif
 
1731
 
 
1732
    mp4state.paused = 1;
 
1733
    module.outMod->Pause(1);
 
1734
}
 
1735
 
 
1736
void unpause()
 
1737
{
 
1738
#ifdef DEBUG_OUTPUT
 
1739
    in_mp4_DebugOutput("unpause");
 
1740
#endif
 
1741
 
 
1742
    mp4state.paused = 0;
 
1743
    module.outMod->Pause(0);
 
1744
}
 
1745
 
 
1746
int ispaused()
 
1747
{
 
1748
#ifdef DEBUG_OUTPUT
 
1749
    in_mp4_DebugOutput("ispaused");
 
1750
#endif
 
1751
 
 
1752
    return mp4state.paused;
 
1753
}
 
1754
 
 
1755
void setvolume(int volume)
 
1756
{
 
1757
#ifdef DEBUG_OUTPUT
 
1758
    in_mp4_DebugOutput("setvolume");
 
1759
#endif
 
1760
 
 
1761
    module.outMod->SetVolume(volume);
 
1762
}
 
1763
 
 
1764
void setpan(int pan)
 
1765
{
 
1766
#ifdef DEBUG_OUTPUT
 
1767
    in_mp4_DebugOutput("setpan");
 
1768
#endif
 
1769
 
 
1770
    module.outMod->SetPan(pan);
 
1771
}
 
1772
 
 
1773
void stop()
 
1774
{
 
1775
    struct seek_list *target = mp4state.m_head;
 
1776
 
 
1777
#ifdef DEBUG_OUTPUT
 
1778
    in_mp4_DebugOutput("stop");
 
1779
#endif
 
1780
 
 
1781
    killPlayThread = 1;
 
1782
 
 
1783
    if (play_thread_handle != INVALID_HANDLE_VALUE)
 
1784
    {
 
1785
        if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
 
1786
            TerminateThread(play_thread_handle,0);
 
1787
        CloseHandle(play_thread_handle);
 
1788
        play_thread_handle = INVALID_HANDLE_VALUE;
 
1789
    }
 
1790
 
 
1791
 
 
1792
    if (mp4state.m_aac_buffer)
 
1793
        free(mp4state.m_aac_buffer);
 
1794
 
 
1795
    while (target)
 
1796
    {
 
1797
        struct seek_list *tmp = target;
 
1798
        target = target->next;
 
1799
        if (tmp) free(tmp);
 
1800
    }
 
1801
    NeAACDecClose(mp4state.hDecoder);
 
1802
    if (mp4state.filetype)
 
1803
        fclose(mp4state.aacfile);
 
1804
    else {
 
1805
        mp4ff_close(mp4state.mp4file);
 
1806
        fclose(mp4state.mp4File);
 
1807
    }
 
1808
 
 
1809
    module.outMod->Close();
 
1810
    module.SAVSADeInit();
 
1811
 
 
1812
    mp4state.filename[0] = '\0';
 
1813
}
 
1814
 
 
1815
int getsonglength(const char *fn)
 
1816
{
 
1817
    long msDuration = 0;
 
1818
 
 
1819
    if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
 
1820
    {
 
1821
        int track;
 
1822
        int64_t length;
 
1823
        FILE *mp4File;
 
1824
        mp4ff_t *file;
 
1825
        mp4ff_callback_t mp4cb = {0};
 
1826
 
 
1827
        mp4File = fopen(fn, "rb");
 
1828
        mp4cb.read = read_callback;
 
1829
        mp4cb.seek = seek_callback;
 
1830
        mp4cb.user_data = mp4File;
 
1831
 
 
1832
 
 
1833
        file = mp4ff_open_read(&mp4cb);
 
1834
        if (file == NULL)
 
1835
            return 0;
 
1836
 
 
1837
        if ((track = GetAACTrack(file)) < 0)
 
1838
        {
 
1839
            mp4ff_close(file);
 
1840
            fclose(mp4File);
 
1841
            return -1;
 
1842
        }
 
1843
 
 
1844
        length = mp4ff_get_track_duration(file, track);
 
1845
 
 
1846
        msDuration = (long)((float)length*1000.0 / (float)mp4ff_time_scale(file, track) + 0.5);
 
1847
 
 
1848
        mp4ff_close(file);
 
1849
        fclose(mp4File);
 
1850
 
 
1851
        return msDuration;
 
1852
    } else {
 
1853
        int tagsize = 0;
 
1854
        int bread = 0;
 
1855
        double length = 0.;
 
1856
        __int64 bitrate = 128;
 
1857
        struct seek_list *target;
 
1858
        state len_state;
 
1859
 
 
1860
        memset(&len_state, 0, sizeof(state));
 
1861
 
 
1862
        if (!(len_state.aacfile = fopen(fn, "rb")))
 
1863
        {
 
1864
            // error
 
1865
            return 0;
 
1866
        }
 
1867
 
 
1868
        len_state.m_at_eof = 0;
 
1869
 
 
1870
        if (!(len_state.m_aac_buffer = (unsigned char*)malloc(768*6)))
 
1871
        {
 
1872
            //console::error("Memory allocation error.", "foo_mp4");
 
1873
            return 0;
 
1874
        }
 
1875
        memset(len_state.m_aac_buffer, 0, 768*6);
 
1876
 
 
1877
        bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
 
1878
        len_state.m_aac_bytes_into_buffer = bread;
 
1879
        len_state.m_aac_bytes_consumed = 0;
 
1880
        len_state.m_file_offset = 0;
 
1881
 
 
1882
        if (bread != 768*6)
 
1883
            len_state.m_at_eof = 1;
 
1884
 
 
1885
        if (!memcmp(len_state.m_aac_buffer, "ID3", 3))
 
1886
        {
 
1887
            /* high bit is not used */
 
1888
            tagsize = (len_state.m_aac_buffer[6] << 21) | (len_state.m_aac_buffer[7] << 14) |
 
1889
                (len_state.m_aac_buffer[8] <<  7) | (len_state.m_aac_buffer[9] <<  0);
 
1890
 
 
1891
            tagsize += 10;
 
1892
            advance_buffer(&len_state, tagsize);
 
1893
        }
 
1894
 
 
1895
        len_state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
 
1896
        len_state.m_tail = len_state.m_head;
 
1897
        len_state.m_tail->next = NULL;
 
1898
 
 
1899
        len_state.m_header_type = 0;
 
1900
        if ((len_state.m_aac_buffer[0] == 0xFF) && ((len_state.m_aac_buffer[1] & 0xF6) == 0xF0))
 
1901
        {
 
1902
            if (1) //(m_reader->can_seek())
 
1903
            {
 
1904
                adts_parse(&len_state, &bitrate, &length);
 
1905
                fseek(len_state.aacfile, tagsize, SEEK_SET);
 
1906
 
 
1907
                bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
 
1908
                if (bread != 768*6)
 
1909
                    len_state.m_at_eof = 1;
 
1910
                else
 
1911
                    len_state.m_at_eof = 0;
 
1912
                len_state.m_aac_bytes_into_buffer = bread;
 
1913
                len_state.m_aac_bytes_consumed = 0;
 
1914
 
 
1915
                len_state.m_header_type = 1;
 
1916
            }
 
1917
        } else if (memcmp(len_state.m_aac_buffer, "ADIF", 4) == 0) {
 
1918
            int skip_size = (len_state.m_aac_buffer[4] & 0x80) ? 9 : 0;
 
1919
            bitrate = ((unsigned int)(len_state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
 
1920
                ((unsigned int)len_state.m_aac_buffer[5 + skip_size]<<11) |
 
1921
                ((unsigned int)len_state.m_aac_buffer[6 + skip_size]<<3) |
 
1922
                ((unsigned int)len_state.m_aac_buffer[7 + skip_size] & 0xE0);
 
1923
 
 
1924
            length = (double)file_length(len_state.aacfile);
 
1925
            if (length == -1)
 
1926
                length = 0;
 
1927
            else
 
1928
                length = ((double)length*8.)/((double)bitrate) + 0.5;
 
1929
 
 
1930
            len_state.m_header_type = 2;
 
1931
        } else {
 
1932
            length = (double)file_length(len_state.aacfile);
 
1933
            length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
 
1934
 
 
1935
            len_state.m_header_type = 0;
 
1936
        }
 
1937
 
 
1938
        if (len_state.m_aac_buffer)
 
1939
            free(len_state.m_aac_buffer);
 
1940
 
 
1941
        target = len_state.m_head;
 
1942
        while (target)
 
1943
        {
 
1944
            struct seek_list *tmp = target;
 
1945
            target = target->next;
 
1946
            if (tmp) free(tmp);
 
1947
        }
 
1948
 
 
1949
        fclose(len_state.aacfile);
 
1950
 
 
1951
        return (int)(length*1000.);
 
1952
    }
 
1953
}
 
1954
 
 
1955
int getlength()
 
1956
{
 
1957
    if (!mp4state.filetype)
 
1958
    {
 
1959
        int track;
 
1960
        long msDuration;
 
1961
        long length;
 
1962
 
 
1963
        if ((track = GetAACTrack(mp4state.mp4file)) < 0)
 
1964
        {
 
1965
            return -1;
 
1966
        }
 
1967
 
 
1968
        length = mp4ff_get_track_duration(mp4state.mp4file, track);
 
1969
 
 
1970
        msDuration = (long)(length*1000.0 / (float)mp4ff_time_scale(mp4state.mp4file, track) + 0.5);
 
1971
 
 
1972
        return msDuration;
 
1973
    } else {
 
1974
        return mp4state.m_length;
 
1975
    }
 
1976
    return 0;
 
1977
}
 
1978
 
 
1979
int getoutputtime()
 
1980
{
 
1981
    return mp4state.decode_pos_ms+(module.outMod->GetOutputTime()-module.outMod->GetWrittenTime());
 
1982
}
 
1983
 
 
1984
void setoutputtime(int time_in_ms)
 
1985
{
 
1986
#ifdef DEBUG_OUTPUT
 
1987
    in_mp4_DebugOutput("setoutputtime");
 
1988
#endif
 
1989
 
 
1990
    mp4state.seek_needed = time_in_ms;
 
1991
}
 
1992
 
 
1993
void getfileinfo(char *filename, char *title, int *length_in_ms)
 
1994
{
 
1995
    if (!filename || !*filename)  /* currently playing file */
 
1996
    {
 
1997
        if (length_in_ms)
 
1998
            *length_in_ms = getlength();
 
1999
 
 
2000
        if (title)
 
2001
        {
 
2002
            if (mp4state.filetype == 0)
 
2003
            {
 
2004
                ConstructTitle(mp4state.mp4file, mp4state.filename, title, titleformat);
 
2005
            } else {
 
2006
                char *tmp2;
 
2007
                char *tmp = PathFindFileName(mp4state.filename);
 
2008
                strcpy(title, tmp);
 
2009
                tmp2 = strrchr(title, '.');
 
2010
                tmp2[0] = '\0';
 
2011
            }
 
2012
        }
 
2013
    } else {
 
2014
        if (length_in_ms)
 
2015
            *length_in_ms = getsonglength(filename);
 
2016
 
 
2017
        if (title)
 
2018
        {
 
2019
            unsigned char header[8];
 
2020
            FILE *hMP4File = fopen(filename, "rb");
 
2021
            if (!hMP4File)
 
2022
            {
 
2023
                return;
 
2024
            }
 
2025
            fread(header, 1, 8, hMP4File);
 
2026
            fclose(hMP4File);
 
2027
 
 
2028
            if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
 
2029
            {
 
2030
                FILE *mp4File;
 
2031
                mp4ff_t *file;
 
2032
                mp4ff_callback_t mp4cb = {0};
 
2033
 
 
2034
                mp4File = fopen(filename, "rb");
 
2035
                mp4cb.read = read_callback;
 
2036
                mp4cb.seek = seek_callback;
 
2037
                mp4cb.user_data = mp4File;
 
2038
 
 
2039
                file = mp4ff_open_read(&mp4cb);
 
2040
                if (file == NULL)
 
2041
                    return;
 
2042
 
 
2043
                ConstructTitle(file, filename, title, titleformat);
 
2044
 
 
2045
                mp4ff_close(file);
 
2046
                fclose(mp4File);
 
2047
            } else {
 
2048
                char *tmp2;
 
2049
                char *tmp = PathFindFileName(filename);
 
2050
                strcpy(title, tmp);
 
2051
                tmp2 = strrchr(title, '.');
 
2052
                tmp2[0] = '\0';
 
2053
            }
 
2054
        }
 
2055
    }
 
2056
}
 
2057
 
 
2058
void eq_set(int on, char data[10], int preamp)
 
2059
{
 
2060
}
 
2061
 
 
2062
static void remap_channels(unsigned char *data, unsigned int samples, unsigned int bps)
 
2063
{
 
2064
    unsigned int i;
 
2065
 
 
2066
    switch (bps)
 
2067
    {
 
2068
    case 8:
 
2069
        {
 
2070
            unsigned char r1, r2, r3, r4, r5, r6;
 
2071
            for (i = 0; i < samples; i += 6)
 
2072
            {
 
2073
                r1 = data[i];
 
2074
                r2 = data[i+1];
 
2075
                r3 = data[i+2];
 
2076
                r4 = data[i+3];
 
2077
                r5 = data[i+4];
 
2078
                r6 = data[i+5];
 
2079
                data[i] = r2;
 
2080
                data[i+1] = r3;
 
2081
                data[i+2] = r1;
 
2082
                data[i+3] = r6;
 
2083
                data[i+4] = r4;
 
2084
                data[i+5] = r5;
 
2085
            }
 
2086
        }
 
2087
        break;
 
2088
 
 
2089
    case 16:
 
2090
    default:
 
2091
        {
 
2092
            unsigned short r1, r2, r3, r4, r5, r6;
 
2093
            unsigned short *sample_buffer = (unsigned short *)data;
 
2094
            for (i = 0; i < samples; i += 6)
 
2095
            {
 
2096
                r1 = sample_buffer[i];
 
2097
                r2 = sample_buffer[i+1];
 
2098
                r3 = sample_buffer[i+2];
 
2099
                r4 = sample_buffer[i+3];
 
2100
                r5 = sample_buffer[i+4];
 
2101
                r6 = sample_buffer[i+5];
 
2102
                sample_buffer[i] = r2;
 
2103
                sample_buffer[i+1] = r3;
 
2104
                sample_buffer[i+2] = r1;
 
2105
                sample_buffer[i+3] = r6;
 
2106
                sample_buffer[i+4] = r4;
 
2107
                sample_buffer[i+5] = r5;
 
2108
            }
 
2109
        }
 
2110
        break;
 
2111
 
 
2112
    case 24:
 
2113
    case 32:
 
2114
        {
 
2115
            unsigned int r1, r2, r3, r4, r5, r6;
 
2116
            unsigned int *sample_buffer = (unsigned int *)data;
 
2117
            for (i = 0; i < samples; i += 6)
 
2118
            {
 
2119
                r1 = sample_buffer[i];
 
2120
                r2 = sample_buffer[i+1];
 
2121
                r3 = sample_buffer[i+2];
 
2122
                r4 = sample_buffer[i+3];
 
2123
                r5 = sample_buffer[i+4];
 
2124
                r6 = sample_buffer[i+5];
 
2125
                sample_buffer[i] = r2;
 
2126
                sample_buffer[i+1] = r3;
 
2127
                sample_buffer[i+2] = r1;
 
2128
                sample_buffer[i+3] = r6;
 
2129
                sample_buffer[i+4] = r4;
 
2130
                sample_buffer[i+5] = r5;
 
2131
            }
 
2132
        }
 
2133
        break;
 
2134
    }
 
2135
}
 
2136
 
 
2137
DWORD WINAPI MP4PlayThread(void *b)
 
2138
{
 
2139
    int done = 0;
 
2140
    int l;
 
2141
    int seq_frames = 0;
 
2142
    int seq_bytes = 0;
 
2143
 
 
2144
    void *sample_buffer;
 
2145
    unsigned char *buffer;
 
2146
    int buffer_size;
 
2147
    NeAACDecFrameInfo frameInfo;
 
2148
 
 
2149
#ifdef DEBUG_OUTPUT
 
2150
    in_mp4_DebugOutput("MP4PlayThread");
 
2151
#endif
 
2152
 
 
2153
    PlayThreadAlive = 1;
 
2154
    mp4state.last_frame = 0;
 
2155
    mp4state.initial = 1;
 
2156
 
 
2157
    while (!*((int *)b))
 
2158
    {
 
2159
        /* seeking */
 
2160
        if (mp4state.seek_needed != -1)
 
2161
        {
 
2162
            int64_t duration;
 
2163
            int32_t skip_samples = 0;
 
2164
 
 
2165
            module.outMod->Flush(mp4state.decode_pos_ms);
 
2166
            duration = (int64_t)(mp4state.seek_needed/1000.0 * mp4state.samplerate + 0.5);
 
2167
            mp4state.sampleId = mp4ff_find_sample_use_offsets(mp4state.mp4file,
 
2168
                mp4state.mp4track, duration, &skip_samples);
 
2169
 
 
2170
            mp4state.decode_pos_ms = mp4state.seek_needed;
 
2171
            mp4state.seek_needed = -1;
 
2172
        }
 
2173
 
 
2174
        if (done)
 
2175
        {
 
2176
            module.outMod->CanWrite();
 
2177
 
 
2178
            if (!module.outMod->IsPlaying())
 
2179
            {
 
2180
                PostMessage(module.hMainWindow, WM_WA_AAC_EOF, 0, 0);
 
2181
                PlayThreadAlive = 0;
 
2182
                return 0;
 
2183
            }
 
2184
 
 
2185
            Sleep(10);
 
2186
        } else if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short))) {
 
2187
 
 
2188
            if (mp4state.last_frame)
 
2189
            {
 
2190
                done = 1;
 
2191
            } else {
 
2192
                int rc;
 
2193
 
 
2194
                /* for gapless decoding */
 
2195
                char *buf;
 
2196
                long dur;
 
2197
                unsigned int sample_count;
 
2198
                unsigned int delay = 0;
 
2199
 
 
2200
                /* get acces unit from MP4 file */
 
2201
                buffer = NULL;
 
2202
                buffer_size = 0;
 
2203
 
 
2204
                dur = mp4ff_get_sample_duration(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId);
 
2205
                rc = mp4ff_read_sample(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId++, &buffer,  &buffer_size);
 
2206
 
 
2207
                if (mp4state.sampleId == 1) dur = 0;
 
2208
                if (rc == 0 || buffer == NULL)
 
2209
                {
 
2210
                    mp4state.last_frame = 1;
 
2211
                    sample_buffer = NULL;
 
2212
                    frameInfo.samples = 0;
 
2213
                } else {
 
2214
                    sample_buffer = NeAACDecDecode(mp4state.hDecoder, &frameInfo,
 
2215
                        buffer, buffer_size);
 
2216
                }
 
2217
                if (frameInfo.error > 0)
 
2218
                {
 
2219
                    show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
 
2220
                    mp4state.last_frame = 1;
 
2221
                }
 
2222
                if (mp4state.sampleId >= mp4state.numSamples)
 
2223
                    mp4state.last_frame = 1;
 
2224
 
 
2225
                if (buffer) free(buffer);
 
2226
 
 
2227
                if (mp4state.useAacLength || (mp4state.timescale != mp4state.samplerate)) {
 
2228
                    sample_count = frameInfo.samples;
 
2229
                } else {
 
2230
                    sample_count = (unsigned int)(dur * frameInfo.channels);
 
2231
 
 
2232
                    if (!mp4state.useAacLength && !mp4state.initial && (mp4state.sampleId < mp4state.numSamples/2) && (dur*frameInfo.channels != frameInfo.samples))
 
2233
                    {
 
2234
                        //fprintf(stderr, "MP4 seems to have incorrect frame duration, using values from AAC data.\n");
 
2235
                        mp4state.useAacLength = 1;
 
2236
                        sample_count = frameInfo.samples;
 
2237
                    }
 
2238
                }
 
2239
 
 
2240
                if (mp4state.initial && (sample_count < mp4state.framesize*mp4state.channels) && (frameInfo.samples > sample_count))
 
2241
                {
 
2242
                    delay = frameInfo.samples - sample_count;
 
2243
                }
 
2244
 
 
2245
                if (!killPlayThread && (sample_count > 0))
 
2246
                {
 
2247
                    buf = (char *)sample_buffer;
 
2248
                    mp4state.initial = 0;
 
2249
 
 
2250
                    switch (res_table[m_resolution])
 
2251
                    {
 
2252
                    case 8:
 
2253
                        buf += delay;
 
2254
                        break;
 
2255
                    case 16:
 
2256
                    default:
 
2257
                        buf += delay * 2;
 
2258
                        break;
 
2259
                    case 24:
 
2260
                    case 32:
 
2261
                        buf += delay * 4;
 
2262
                        break;
 
2263
                    case 64:
 
2264
                        buf += delay * 8;
 
2265
                    }
 
2266
 
 
2267
                    if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
 
2268
                        remap_channels(buf, sample_count, res_table[m_resolution]);
 
2269
 
 
2270
                    if (res_table[m_resolution] == 24)
 
2271
                    {
 
2272
                        /* convert libfaad output (3 bytes packed in 4) */
 
2273
                        char *temp_buffer = convert3in4to3in3(buf, sample_count);
 
2274
                        memcpy((void*)buf, (void*)temp_buffer, sample_count*3);
 
2275
                        free(temp_buffer);
 
2276
                    }
 
2277
 
 
2278
                    module.SAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
 
2279
                        mp4state.decode_pos_ms);
 
2280
                    module.VSAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
 
2281
                        mp4state.decode_pos_ms);
 
2282
                    mp4state.decode_pos_ms += (double)sample_count * 1000.0 /
 
2283
                        ((double)frameInfo.samplerate * (double)frameInfo.channels);
 
2284
 
 
2285
                    l = sample_count * res_table[m_resolution] / 8;
 
2286
 
 
2287
                    if (module.dsp_isactive())
 
2288
                    {
 
2289
                        void *dsp_buffer = malloc(l*2);
 
2290
                        memcpy(dsp_buffer, buf, l);
 
2291
 
 
2292
                        l = module.dsp_dosamples((short*)dsp_buffer,
 
2293
                            sample_count/frameInfo.channels,
 
2294
                            res_table[m_resolution],
 
2295
                            frameInfo.channels,
 
2296
                            frameInfo.samplerate) *
 
2297
                            (frameInfo.channels*(res_table[m_resolution]/8));
 
2298
 
 
2299
                        module.outMod->Write(dsp_buffer, l);
 
2300
                        if (dsp_buffer) free(dsp_buffer);
 
2301
                    } else {
 
2302
                        module.outMod->Write(buf, l);
 
2303
                    }
 
2304
 
 
2305
                    /* VBR bitrate display */
 
2306
                    if (m_vbr_display)
 
2307
                    {
 
2308
                        seq_frames++;
 
2309
                        seq_bytes += frameInfo.bytesconsumed;
 
2310
                        if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(sample_count/frameInfo.channels) + 0.5)))
 
2311
                        {
 
2312
                            module.SetInfo((int)floor(((float)seq_bytes*8.)/1000. + 0.5),
 
2313
                                (int)floor(frameInfo.samplerate/1000. + 0.5),
 
2314
                                mp4state.channels, 1);
 
2315
 
 
2316
                            seq_frames = 0;
 
2317
                            seq_bytes = 0;
 
2318
                        }
 
2319
                    }
 
2320
                }
 
2321
            }
 
2322
        } else {
 
2323
            Sleep(10);
 
2324
        }
 
2325
    }
 
2326
 
 
2327
    PlayThreadAlive = 0;
 
2328
 
 
2329
    return 0;
 
2330
}
 
2331
 
 
2332
void *decode_aac_frame(state *st, NeAACDecFrameInfo *frameInfo)
 
2333
{
 
2334
    void *sample_buffer = NULL;
 
2335
 
 
2336
    do
 
2337
    {
 
2338
        fill_buffer(st);
 
2339
 
 
2340
        if (st->m_aac_bytes_into_buffer != 0)
 
2341
        {
 
2342
            sample_buffer = NeAACDecDecode(st->hDecoder, frameInfo,
 
2343
                st->m_aac_buffer, st->m_aac_bytes_into_buffer);
 
2344
 
 
2345
            if (st->m_header_type != 1)
 
2346
            {
 
2347
                if (st->last_offset < st->m_file_offset)
 
2348
                {
 
2349
                    st->m_tail->offset = st->m_file_offset;
 
2350
                    st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
 
2351
                    st->m_tail = st->m_tail->next;
 
2352
                    st->m_tail->next = NULL;
 
2353
                    st->last_offset = st->m_file_offset;
 
2354
                }
 
2355
            }
 
2356
 
 
2357
            advance_buffer(st, frameInfo->bytesconsumed);
 
2358
        } else {
 
2359
            break;
 
2360
        }
 
2361
 
 
2362
    } while (!frameInfo->samples && !frameInfo->error);
 
2363
 
 
2364
    return sample_buffer;
 
2365
}
 
2366
 
 
2367
int aac_seek(state *st, double seconds)
 
2368
{
 
2369
    int i, frames;
 
2370
    int bread;
 
2371
    struct seek_list *target = st->m_head;
 
2372
 
 
2373
    if (1 /*can_seek*/ && ((st->m_header_type == 1) || (seconds < st->cur_pos_sec)))
 
2374
    {
 
2375
        frames = (int)(seconds*((double)st->samplerate/(double)st->framesize) + 0.5);
 
2376
 
 
2377
        for (i = 0; i < frames; i++)
 
2378
        {
 
2379
            if (target->next)
 
2380
                target = target->next;
 
2381
            else
 
2382
                return 0;
 
2383
        }
 
2384
        if (target->offset == 0 && frames > 0)
 
2385
            return 0;
 
2386
        fseek(st->aacfile, target->offset, SEEK_SET);
 
2387
        st->m_file_offset = target->offset;
 
2388
 
 
2389
        bread = fread(st->m_aac_buffer, 1, 768*6, st->aacfile);
 
2390
        if (bread != 768*6)
 
2391
            st->m_at_eof = 1;
 
2392
        else
 
2393
            st->m_at_eof = 0;
 
2394
        st->m_aac_bytes_into_buffer = bread;
 
2395
        st->m_aac_bytes_consumed = 0;
 
2396
        st->m_file_offset += bread;
 
2397
 
 
2398
        NeAACDecPostSeekReset(st->hDecoder, -1);
 
2399
 
 
2400
        return 1;
 
2401
    } else {
 
2402
        if (seconds > st->cur_pos_sec)
 
2403
        {
 
2404
            NeAACDecFrameInfo frameInfo;
 
2405
 
 
2406
            frames = (int)((seconds - st->cur_pos_sec)*((double)st->samplerate/(double)st->framesize));
 
2407
 
 
2408
            if (frames > 0)
 
2409
            {
 
2410
                for (i = 0; i < frames; i++)
 
2411
                {
 
2412
                    memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
 
2413
                    decode_aac_frame(st, &frameInfo);
 
2414
 
 
2415
                    if (frameInfo.error || (st->m_aac_bytes_into_buffer == 0))
 
2416
                    {
 
2417
                        if (frameInfo.error)
 
2418
                        {
 
2419
                            if (NeAACDecGetErrorMessage(frameInfo.error) != NULL)
 
2420
                                show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
 
2421
                        }
 
2422
                        return 0;
 
2423
                    }
 
2424
                }
 
2425
            }
 
2426
 
 
2427
            NeAACDecPostSeekReset(st->hDecoder, -1);
 
2428
        }
 
2429
        return 1;
 
2430
    }
 
2431
}
 
2432
 
 
2433
DWORD WINAPI AACPlayThread(void *b)
 
2434
{
 
2435
    int done = 0;
 
2436
    int l;
 
2437
    int seq_frames = 0;
 
2438
    int seq_bytes = 0;
 
2439
 
 
2440
#ifdef DEBUG_OUTPUT
 
2441
    in_mp4_DebugOutput("AACPlayThread");
 
2442
#endif
 
2443
 
 
2444
    PlayThreadAlive = 1;
 
2445
    mp4state.last_frame = 0;
 
2446
 
 
2447
    while (!*((int *)b))
 
2448
    {
 
2449
        /* seeking */
 
2450
        if (mp4state.seek_needed != -1)
 
2451
        {
 
2452
            double ms;
 
2453
 
 
2454
            ms = mp4state.seek_needed/1000;
 
2455
            if (aac_seek(&mp4state, ms)!=0)
 
2456
            {
 
2457
                module.outMod->Flush(mp4state.decode_pos_ms);
 
2458
                mp4state.cur_pos_sec = ms;
 
2459
                mp4state.decode_pos_ms = mp4state.seek_needed;
 
2460
            }
 
2461
            mp4state.seek_needed = -1;
 
2462
        }
 
2463
 
 
2464
        if (done)
 
2465
        {
 
2466
            module.outMod->CanWrite();
 
2467
 
 
2468
            if (!module.outMod->IsPlaying())
 
2469
            {
 
2470
                PostMessage(module.hMainWindow, WM_WA_AAC_EOF, 0, 0);
 
2471
                PlayThreadAlive = 0;
 
2472
                return 0;
 
2473
            }
 
2474
 
 
2475
            Sleep(10);
 
2476
        } else if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short))) {
 
2477
            NeAACDecFrameInfo frameInfo;
 
2478
            void *sample_buffer;
 
2479
 
 
2480
            memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
 
2481
 
 
2482
            sample_buffer = decode_aac_frame(&mp4state, &frameInfo);
 
2483
 
 
2484
            if (frameInfo.error || (mp4state.m_aac_bytes_into_buffer == 0))
 
2485
            {
 
2486
                if (frameInfo.error)
 
2487
                {
 
2488
                    if (NeAACDecGetErrorMessage(frameInfo.error) != NULL)
 
2489
                        show_error(module.hMainWindow, NeAACDecGetErrorMessage(frameInfo.error));
 
2490
                }
 
2491
                done = 1;
 
2492
            }
 
2493
 
 
2494
            if (!killPlayThread && (frameInfo.samples > 0))
 
2495
            {
 
2496
                if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
 
2497
                    remap_channels(sample_buffer, frameInfo.samples, res_table[m_resolution]);
 
2498
 
 
2499
                if (res_table[m_resolution] == 24)
 
2500
                {
 
2501
                    /* convert libfaad output (3 bytes packed in 4 bytes) */
 
2502
                    char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
 
2503
                    memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
 
2504
                    free(temp_buffer);
 
2505
                }
 
2506
 
 
2507
                module.SAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
 
2508
                    mp4state.decode_pos_ms);
 
2509
                module.VSAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
 
2510
                    mp4state.decode_pos_ms);
 
2511
                mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
 
2512
                    ((double)frameInfo.samplerate* (double)frameInfo.channels);
 
2513
 
 
2514
                l = frameInfo.samples * res_table[m_resolution] / 8;
 
2515
 
 
2516
                if (module.dsp_isactive())
 
2517
                {
 
2518
                    void *dsp_buffer = malloc(l*2);
 
2519
                    memcpy(dsp_buffer, sample_buffer, l);
 
2520
 
 
2521
                    l = module.dsp_dosamples((short*)dsp_buffer,
 
2522
                        frameInfo.samples/frameInfo.channels,
 
2523
                        res_table[m_resolution],
 
2524
                        frameInfo.channels,
 
2525
                        frameInfo.samplerate) *
 
2526
                        (frameInfo.channels*(res_table[m_resolution]/8));
 
2527
 
 
2528
                    module.outMod->Write(dsp_buffer, l);
 
2529
                    if (dsp_buffer) free(dsp_buffer);
 
2530
                } else {
 
2531
                    module.outMod->Write(sample_buffer, l);
 
2532
                }
 
2533
 
 
2534
                /* VBR bitrate display */
 
2535
                if (m_vbr_display)
 
2536
                {
 
2537
                    seq_frames++;
 
2538
                    seq_bytes += frameInfo.bytesconsumed;
 
2539
                    if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(frameInfo.samples/frameInfo.channels) + 0.5)))
 
2540
                    {
 
2541
                        module.SetInfo((int)floor(((float)seq_bytes*8.)/1000. + 0.5),
 
2542
                            (int)floor(frameInfo.samplerate/1000. + 0.5),
 
2543
                            mp4state.channels, 1);
 
2544
 
 
2545
                        seq_frames = 0;
 
2546
                        seq_bytes = 0;
 
2547
                    }
 
2548
                }
 
2549
            }
 
2550
 
 
2551
            if (frameInfo.channels > 0 && mp4state.samplerate > 0)
 
2552
                mp4state.cur_pos_sec += ((double)(frameInfo.samples/frameInfo.channels))/(double)mp4state.samplerate;
 
2553
        } else {
 
2554
            Sleep(10);
 
2555
        }
 
2556
    }
 
2557
 
 
2558
    PlayThreadAlive = 0;
 
2559
 
 
2560
    return 0;
 
2561
}
 
2562
 
 
2563
static In_Module module =
 
2564
{
 
2565
    IN_VER,
 
2566
    "AudioCoding.com MPEG-4 AAC player: " FAAD2_VERSION " compiled on " __DATE__,
 
2567
    0,  // hMainWindow
 
2568
    0,  // hDllInstance
 
2569
    NULL,
 
2570
    1, // is_seekable
 
2571
    1, // uses output
 
2572
    config,
 
2573
    about,
 
2574
    init,
 
2575
    quit,
 
2576
    getfileinfo,
 
2577
    infoDlg,
 
2578
    isourfile,
 
2579
    play,
 
2580
    pause,
 
2581
    unpause,
 
2582
    ispaused,
 
2583
    stop,
 
2584
 
 
2585
    getlength,
 
2586
    getoutputtime,
 
2587
    setoutputtime,
 
2588
 
 
2589
    setvolume,
 
2590
    setpan,
 
2591
 
 
2592
    0,0,0,0,0,0,0,0,0, // vis stuff
 
2593
 
 
2594
 
 
2595
    0,0, // dsp
 
2596
 
 
2597
    eq_set,
 
2598
 
 
2599
    NULL,       // setinfo
 
2600
 
 
2601
    0 // out_mod
 
2602
};
 
2603
 
 
2604
__declspec(dllexport) In_Module* winampGetInModule2()
 
2605
{
 
2606
    config_read();
 
2607
 
 
2608
    if (!m_use_for_aac)
 
2609
    {
 
2610
        module.FileExtensions = short_ext_list;
 
2611
    } else {
 
2612
        module.FileExtensions = long_ext_list;
 
2613
    }
 
2614
 
 
2615
    return &module;
 
2616
}
 
2617
 
 
2618
/* new Media Library interface */
 
2619
 
 
2620
int mp4_get_metadata(mp4ff_t *file, const char *item, char *dest, int dlen)
 
2621
{
 
2622
    char *pVal = NULL, dummy1[4096];
 
2623
 
 
2624
    if (dlen < 1) return 0;
 
2625
 
 
2626
    if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
 
2627
    {
 
2628
        if (mp4ff_meta_get_track(file, &pVal))
 
2629
        {
 
2630
            wsprintf(dummy1, "%s", pVal);
 
2631
            strncpy(dest, dummy1, dlen-1);
 
2632
            dest[dlen-1] = '\0';
 
2633
            return 1;
 
2634
        }
 
2635
    }
 
2636
    else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
 
2637
    {
 
2638
        if (mp4ff_meta_get_disc(file, &pVal))
 
2639
        {
 
2640
            wsprintf(dummy1, "%s", pVal);
 
2641
            strncpy(dest, dummy1, dlen-1);
 
2642
            dest[dlen-1] = '\0';
 
2643
            return 1;
 
2644
        }
 
2645
    }
 
2646
    else if (!stricmp(item, "compilation"))
 
2647
    {
 
2648
        uint8_t cpil = 0;
 
2649
        if (mp4ff_meta_get_compilation(file, &pVal))
 
2650
        {
 
2651
            wsprintf(dummy1, "%s", pVal);
 
2652
            strncpy(dest, dummy1, dlen-1);
 
2653
            dest[dlen-1] = '\0';
 
2654
            return 1;
 
2655
        }
 
2656
    }
 
2657
    else if (!stricmp(item, "tempo"))
 
2658
    {
 
2659
        if (mp4ff_meta_get_tempo(file, &pVal))
 
2660
        {
 
2661
            wsprintf(dummy1, "%s", pVal);
 
2662
            strncpy(dest, dummy1, dlen-1);
 
2663
            dest[dlen-1] = '\0';
 
2664
            return 1;
 
2665
        }
 
2666
    }
 
2667
    else if (!stricmp(item, "artist"))
 
2668
    {
 
2669
        if (mp4ff_meta_get_artist(file, &pVal))
 
2670
        {
 
2671
            strncpy(dest, pVal, dlen-1);
 
2672
            dest[dlen-1] = '\0';
 
2673
            return 1;
 
2674
        }
 
2675
    }
 
2676
    else if (!stricmp(item, "writer"))
 
2677
    {
 
2678
        if (mp4ff_meta_get_writer(file, &pVal))
 
2679
        {
 
2680
            strncpy(dest, pVal, dlen-1);
 
2681
            dest[dlen-1] = '\0';
 
2682
            return 1;
 
2683
        }
 
2684
    }
 
2685
    else if (!stricmp(item, "title"))
 
2686
    {
 
2687
        if (mp4ff_meta_get_title(file, &pVal))
 
2688
        {
 
2689
            strncpy(dest, pVal, dlen-1);
 
2690
            dest[dlen-1] = '\0';
 
2691
            return 1;
 
2692
        }
 
2693
    }
 
2694
    else if (!stricmp(item, "album"))
 
2695
    {
 
2696
        if (mp4ff_meta_get_album(file, &pVal))
 
2697
        {
 
2698
            strncpy(dest, pVal, dlen-1);
 
2699
            dest[dlen-1] = '\0';
 
2700
            return 1;
 
2701
        }
 
2702
    }
 
2703
    else if (!stricmp(item, "date") || !stricmp(item, "year"))
 
2704
    {
 
2705
        if (mp4ff_meta_get_date(file, &pVal))
 
2706
        {
 
2707
            strncpy(dest, pVal, dlen-1);
 
2708
            dest[dlen-1] = '\0';
 
2709
            return 1;
 
2710
        }
 
2711
    }
 
2712
    else if (!stricmp(item, "comment"))
 
2713
    {
 
2714
        if (mp4ff_meta_get_comment(file, &pVal))
 
2715
        {
 
2716
            strncpy(dest, pVal, dlen-1);
 
2717
            dest[dlen-1] = '\0';
 
2718
            return 1;
 
2719
        }
 
2720
    }
 
2721
    else if (!stricmp(item, "genre"))
 
2722
    {
 
2723
        if (mp4ff_meta_get_genre(file, &pVal))
 
2724
        {
 
2725
            strncpy(dest, pVal, dlen-1);
 
2726
            dest[dlen-1] = '\0';
 
2727
            return 1;
 
2728
        }
 
2729
    }
 
2730
    else if (!stricmp(item, "tool"))
 
2731
    {
 
2732
        if (mp4ff_meta_get_tool(file, &pVal))
 
2733
        {
 
2734
            strncpy(dest, pVal, dlen-1);
 
2735
            dest[dlen-1] = '\0';
 
2736
            return 1;
 
2737
        }
 
2738
    }
 
2739
#if 0
 
2740
    else
 
2741
    {
 
2742
        uint32_t valueSize = 0;
 
2743
        uint8_t *pValue = NULL;
 
2744
 
 
2745
        if (MP4GetMetadataFreeForm(file, (char *)item, &pValue, &valueSize))
 
2746
        {
 
2747
            unsigned int len = (valueSize < (unsigned int)(dlen-1)) ? valueSize : (unsigned int)(dlen-1);
 
2748
            memcpy(dest, pValue, len);
 
2749
            dest[len] = '\0';
 
2750
            return 1;
 
2751
        }
 
2752
    }
 
2753
#endif
 
2754
 
 
2755
    return 0;
 
2756
}
 
2757
 
 
2758
__declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *data, char *dest, int destlen)
 
2759
{
 
2760
    if (!fn || (fn && !*fn) || !destlen) return 0;
 
2761
 
 
2762
    dest[0] = '\0';
 
2763
 
 
2764
    if (!stricmp(data, "length"))
 
2765
    {
 
2766
        char temp[32];
 
2767
        int len = getsonglength(fn);
 
2768
        itoa(len, temp, 10);
 
2769
        strncpy(dest, temp, destlen-1);
 
2770
        dest[destlen-1] = '\0';
 
2771
    }
 
2772
    else
 
2773
    {
 
2774
        char temp[2048], temp2[2048];
 
2775
        FILE *mp4File;
 
2776
        mp4ff_callback_t mp4cb = {0};
 
2777
        mp4ff_t *file;
 
2778
 
 
2779
        mp4File = fopen(fn, "rb");
 
2780
        mp4cb.read = read_callback;
 
2781
        mp4cb.seek = seek_callback;
 
2782
        mp4cb.write = write_callback;
 
2783
        mp4cb.truncate = truncate_callback;
 
2784
        mp4cb.user_data = mp4File;
 
2785
 
 
2786
 
 
2787
        file = mp4ff_open_read(&mp4cb);
 
2788
        if (file == NULL) return 0;
 
2789
 
 
2790
        if (mp4_get_metadata(file, data, temp, sizeof(temp)))
 
2791
        {
 
2792
            int len = ConvertUTF8ToANSI(temp, temp2);
 
2793
            if (len > destlen-1) len = destlen-1;
 
2794
            memcpy(dest, temp2, len);
 
2795
            dest[len] = '\0';
 
2796
        }
 
2797
 
 
2798
        mp4ff_close(file);
 
2799
        fclose(mp4File);
 
2800
    }
 
2801
 
 
2802
    return 1;
 
2803
}
 
2804
 
 
2805
static mp4ff_metadata_t mltags = {0, 0};
 
2806
static BOOL medialib_init = FALSE;
 
2807
static char medialib_lastfn[2048] = "";
 
2808
 
 
2809
__declspec(dllexport) int winampSetExtendedFileInfo(const char *fn, const char *data, char *val)
 
2810
{
 
2811
    int len, ret = 0;
 
2812
    char *temp;
 
2813
 
 
2814
    if (!medialib_init || (medialib_init && stricmp(fn, medialib_lastfn))) {
 
2815
        FILE *mp4File;
 
2816
        mp4ff_callback_t mp4cb = {0};
 
2817
        mp4ff_t *file;
 
2818
        strcpy(medialib_lastfn, fn);
 
2819
 
 
2820
        if (medialib_init) tag_delete(&mltags);
 
2821
 
 
2822
        mp4File = fopen(medialib_lastfn, "rb");
 
2823
        mp4cb.read = read_callback;
 
2824
        mp4cb.seek = seek_callback;
 
2825
        mp4cb.user_data = mp4File;
 
2826
 
 
2827
 
 
2828
        file = mp4ff_open_read(&mp4cb);
 
2829
        if (file == NULL) return 0;
 
2830
 
 
2831
        ReadMP4Tag(file, &mltags);
 
2832
 
 
2833
        mp4ff_close(file);
 
2834
        fclose(mp4File);
 
2835
 
 
2836
        medialib_init = TRUE;
 
2837
    }
 
2838
 
 
2839
    len = strlen(val);
 
2840
    temp = (char *)malloc((len+1)*4);
 
2841
    if (!temp) return 0;
 
2842
 
 
2843
    if (ConvertANSIToUTF8(val, temp))
 
2844
    {
 
2845
        ret = 1;
 
2846
        tag_set_field(&mltags, data, temp, len);
 
2847
    }
 
2848
 
 
2849
    free(temp);
 
2850
 
 
2851
    return ret;
 
2852
}    
 
2853
 
 
2854
__declspec(dllexport) int winampWriteExtendedFileInfo()
 
2855
{
 
2856
    if (medialib_init)
 
2857
    {
 
2858
        FILE *mp4File;
 
2859
        mp4ff_callback_t mp4cb = {0};
 
2860
 
 
2861
        mp4File = fopen(medialib_lastfn, "rb+");
 
2862
        mp4cb.read = read_callback;
 
2863
        mp4cb.seek = seek_callback;
 
2864
        mp4cb.write = write_callback;
 
2865
        mp4cb.truncate = truncate_callback;
 
2866
        mp4cb.user_data = mp4File;
 
2867
 
 
2868
        mp4ff_meta_update(&mp4cb, &mltags);
 
2869
 
 
2870
        fclose(mp4File);
 
2871
 
 
2872
        return 1;
 
2873
    }
 
2874
    else
 
2875
    {
 
2876
        return 0;
 
2877
    }
 
2878
}