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