~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to extras/faad2/plugins/winamp/in_faad.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** FAAD - Freeware Advanced Audio Decoder
 
3
** Copyright (C) 2002 M. Bakker
 
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
** $Id: in_faad.c,v 1.4 2002/11/01 11:19:36 menno Exp $
 
20
**/
 
21
 
 
22
#define WIN32_LEAN_AND_MEAN
 
23
#include <windows.h>
 
24
#include <commctrl.h>
 
25
#include "resource.h"
 
26
 
 
27
#include <faad.h>
 
28
#include <stdlib.h>
 
29
#include <stdio.h>
 
30
#include <aacinfo.h>
 
31
#include <filestream.h>
 
32
#include <id3v2tag.h>
 
33
 
 
34
#include "in2.h"
 
35
 
 
36
 
 
37
static char app_name[] = "AudioCoding.com AAC Player";
 
38
 
 
39
// post this to the main window at end of file (after playback has stopped)
 
40
#define WM_WA_AAC_EOF WM_USER+2
 
41
 
 
42
faadAACInfo file_info;
 
43
 
 
44
faacDecHandle hDecoder;
 
45
faacDecFrameInfo frameInfo;
 
46
 
 
47
In_Module mod; // the output module (declared near the bottom of this file)
 
48
char *lastfn; // currently playing file (used for getting info on the current file)
 
49
int file_length; // file length, in bytes
 
50
int decode_pos_ms; // current decoding position, in milliseconds
 
51
int paused; // are we paused?
 
52
int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
 
53
 
 
54
char *sample_buffer; // sample buffer
 
55
unsigned char *buffer; // input buffer
 
56
unsigned char *memmap_buffer; // input buffer for whole file
 
57
long memmap_index;
 
58
 
 
59
long buffercount, fileread, bytecount;
 
60
 
 
61
// seek table for ADTS header files
 
62
unsigned long *seek_table = NULL;
 
63
int seek_table_length=0;
 
64
 
 
65
int killPlayThread=0; // the kill switch for the decode thread
 
66
int PlayThreadAlive=0; // 1=play thread still running
 
67
HANDLE play_thread_handle=INVALID_HANDLE_VALUE; // the handle to the decode thread
 
68
FILE_STREAM *infile;
 
69
 
 
70
/* Function definitions */
 
71
int id3v2_tag(unsigned char *buffer);
 
72
DWORD WINAPI PlayThread(void *b); // the decode thread procedure
 
73
 
 
74
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
 
75
 
 
76
 
 
77
// 1= use vbr display, 0 = use average bitrate. This value only controls what shows up in the
 
78
// configuration form. Also- Streaming uses an on-the-fly bitrate display regardless of this value.
 
79
long m_variable_bitrate_display=0;
 
80
long m_priority = 5;
 
81
long m_memmap_file = 0;
 
82
char m_format_string[50] = "%1 - %2";
 
83
static char INI_FILE[MAX_PATH];
 
84
 
 
85
char *priority_text[] = {       "",
 
86
                                                        "Decode Thread Priority: Lowest",
 
87
                                                        "Decode Thread Priority: Lower",
 
88
                                                        "Decode Thread Priority: Normal",
 
89
                                                        "Decode Thread Priority: Higher",
 
90
                                                        "Decode Thread Priority: Highest (default)"
 
91
                                                };
 
92
 
 
93
long priority_table[] = {0, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST};
 
94
 
 
95
long current_file_mode = 0;
 
96
 
 
97
int PlayThread_memmap();
 
98
int PlayThread_file();
 
99
 
 
100
static void _r_s(char *name,char *data, int mlen)
 
101
{
 
102
        char buf[10];
 
103
        strcpy(buf,data);
 
104
        GetPrivateProfileString(app_name,name,buf,data,mlen,INI_FILE);
 
105
}
 
106
#define RS(x) (_r_s(#x,x,sizeof(x)))
 
107
#define WS(x) (WritePrivateProfileString(app_name,#x,x,INI_FILE))
 
108
 
 
109
 
 
110
 
 
111
static void config_init()
 
112
{
 
113
        char *p=INI_FILE;
 
114
        GetModuleFileName(NULL,INI_FILE,sizeof(INI_FILE));
 
115
        while (*p) p++;
 
116
        while (p >= INI_FILE && *p != '.') p--;
 
117
        strcpy(p+1,"ini");
 
118
}
 
119
 
 
120
void config_read()
 
121
{
 
122
    char variable_bitrate_display[10];
 
123
    char priority[10];
 
124
    char memmap_file[10];
 
125
    char local_buffer_size[10];
 
126
    char stream_buffer_size[10];
 
127
 
 
128
        config_init();
 
129
 
 
130
    strcpy(variable_bitrate_display, "1");
 
131
    strcpy(priority, "4");
 
132
    strcpy(memmap_file, "0");
 
133
    strcpy(local_buffer_size, "128");
 
134
    strcpy(stream_buffer_size, "64");
 
135
 
 
136
    RS(variable_bitrate_display);
 
137
    RS(priority);
 
138
    RS(m_format_string);
 
139
    RS(memmap_file);
 
140
    RS(local_buffer_size);
 
141
    RS(stream_buffer_size);
 
142
 
 
143
    m_priority = atoi(priority);
 
144
    m_variable_bitrate_display = atoi(variable_bitrate_display);
 
145
    m_memmap_file = atoi(memmap_file);
 
146
    m_local_buffer_size = atoi(local_buffer_size);
 
147
    m_stream_buffer_size = atoi(stream_buffer_size);
 
148
}
 
149
 
 
150
void config_write()
 
151
{
 
152
    char variable_bitrate_display[10];
 
153
    char priority[10];
 
154
    char memmap_file[10];
 
155
    char local_buffer_size[10];
 
156
    char stream_buffer_size[10];
 
157
 
 
158
    itoa(m_priority, priority, 10);
 
159
    itoa(m_variable_bitrate_display, variable_bitrate_display, 10);
 
160
    itoa(m_memmap_file, memmap_file, 10);
 
161
    itoa(m_local_buffer_size, local_buffer_size, 10);
 
162
    itoa(m_stream_buffer_size, stream_buffer_size, 10);
 
163
 
 
164
    WS(variable_bitrate_display);
 
165
    WS(priority);
 
166
    WS(m_format_string);
 
167
    WS(memmap_file);
 
168
    WS(local_buffer_size);
 
169
    WS(stream_buffer_size);
 
170
}
 
171
 
 
172
void config(HWND hwndParent)
 
173
{
 
174
        DialogBox(mod.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG), hwndParent, config_dialog_proc);
 
175
}
 
176
 
 
177
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
 
178
{
 
179
        char tmp[10];
 
180
 
 
181
    switch (message)
 
182
        {
 
183
    case WM_INITDIALOG:
 
184
        
 
185
                SetDlgItemText(hwndDlg, IDC_FORMAT, m_format_string);
 
186
 
 
187
                /* Set priority slider range and previous position */
 
188
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(1, 5)); 
 
189
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, m_priority);
 
190
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
 
191
                
 
192
                /* Put a limit to the amount of characters allowed in the buffer boxes */
 
193
                SendMessage(GetDlgItem(hwndDlg, LOCAL_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
 
194
                SendMessage(GetDlgItem(hwndDlg, STREAM_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
 
195
 
 
196
            if(m_variable_bitrate_display)
 
197
                        SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0);
 
198
            if(m_memmap_file)
 
199
                        SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_CHECKED, 0);
 
200
 
 
201
                itoa(m_local_buffer_size, tmp, 10);
 
202
                SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp);
 
203
 
 
204
                itoa(m_stream_buffer_size, tmp, 10);
 
205
                SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp);
 
206
 
 
207
                return TRUE;
 
208
 
 
209
        case WM_HSCROLL:
 
210
 
 
211
                /* Thread priority slider moved */
 
212
                if(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER) == (HWND) lParam)
 
213
                {
 
214
                        int tmp;
 
215
                        tmp = SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_GETPOS, 0, 0);
 
216
 
 
217
                        if(tmp > 0)
 
218
                        {
 
219
                                m_priority = tmp;
 
220
 
 
221
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
 
222
 
 
223
                                if(play_thread_handle)
 
224
                                        SetThreadPriority(play_thread_handle, priority_table[m_priority]);
 
225
                        }
 
226
                }
 
227
 
 
228
                return TRUE;
 
229
 
 
230
    case WM_COMMAND:
 
231
 
 
232
                if(HIWORD(wParam) == BN_CLICKED)
 
233
                {
 
234
                        if(GetDlgItem(hwndDlg, VARBITRATE_CHK) == (HWND) lParam)
 
235
                        {
 
236
                                /* Variable Bitrate checkbox hit */
 
237
                                m_variable_bitrate_display = SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_GETCHECK, 0, 0); 
 
238
                        }
 
239
                        if(GetDlgItem(hwndDlg, IDC_MEMMAP) == (HWND) lParam)
 
240
                        {
 
241
                                /* Variable Bitrate checkbox hit */
 
242
                                m_memmap_file = SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_GETCHECK, 0, 0); 
 
243
                        }
 
244
                }
 
245
 
 
246
        switch (LOWORD(wParam))
 
247
                {
 
248
                        case OK_BTN:
 
249
                                /* User hit OK, save buffer settings (all others are set on command) */
 
250
                                GetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp, 5);
 
251
                                m_local_buffer_size = atol(tmp);
 
252
 
 
253
                                GetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp, 5);
 
254
                                m_stream_buffer_size = atol(tmp);
 
255
 
 
256
                                GetDlgItemText(hwndDlg, IDC_FORMAT, m_format_string, 50);
 
257
 
 
258
                config_write();
 
259
 
 
260
                        case IDCANCEL:
 
261
                        case CANCEL_BTN:
 
262
                                /* User hit Cancel or the X, just close without saving buffer settings */
 
263
                                EndDialog(hwndDlg, wParam);
 
264
            return TRUE;
 
265
        }
 
266
    }
 
267
    return FALSE;
 
268
}
 
269
 
 
270
void about(HWND hwndParent)
 
271
{
 
272
    MessageBox(hwndParent,"AudioCoding.com AAC Player\n"
 
273
        "Compiled on: " __DATE__ "\n"
 
274
        "http://www.audiocoding.com\n"
 
275
        "Copyright 2002 AudioCoding.com",
 
276
        "About AAC Player",MB_OK);
 
277
}
 
278
 
 
279
void init()
 
280
{
 
281
        char plugin_path[1024];
 
282
        int i;
 
283
 
 
284
    config_read();
 
285
 
 
286
        hInstance_for_id3editor = mod.hDllInstance;
 
287
 
 
288
    buffer = (unsigned char*)LocalAlloc(LPTR, 768*2);
 
289
    lastfn = (char*)LocalAlloc(LPTR, 1024*sizeof(char));
 
290
 
 
291
    /* Initialize winsock, necessary for streaming */
 
292
    WinsockInit();
 
293
}
 
294
 
 
295
void quit()
 
296
{
 
297
    if (lastfn) LocalFree(lastfn);
 
298
    if (buffer) LocalFree(buffer);
 
299
 
 
300
    /* Deallocate winsock */
 
301
    WinsockDeInit();
 
302
 
 
303
        if(seek_table)
 
304
        {
 
305
                free(seek_table);
 
306
                seek_table = NULL;
 
307
                seek_table_length = 0;
 
308
        }
 
309
}
 
310
 
 
311
int isourfile(char *fn)
 
312
{
 
313
    /* Finally fixed */
 
314
    if(StringComp(fn + strlen(fn) - 3, "aac", 3) == 0)
 
315
    {
 
316
        return 1;
 
317
    }
 
318
 
 
319
    return 0;
 
320
}
 
321
 
 
322
unsigned long samplerate, channels;
 
323
 
 
324
int play_memmap(char *fn)
 
325
{
 
326
    int tagsize = 0;
 
327
 
 
328
    infile = open_filestream(fn);
 
329
    
 
330
        if (infile == NULL)
 
331
        return 1;
 
332
 
 
333
    fileread = filelength_filestream(infile);
 
334
 
 
335
    memmap_buffer = (char*)LocalAlloc(LPTR, fileread);
 
336
    read_buffer_filestream(infile, memmap_buffer, fileread);
 
337
 
 
338
    /* skip id3v2 tag */
 
339
    memmap_index = id3v2_tag(memmap_buffer);
 
340
 
 
341
    hDecoder = faacDecOpen();
 
342
 
 
343
        /* Copy the configuration dialog setting and use it as the default */
 
344
        /* initialize the decoder, and get samplerate and channel info */
 
345
 
 
346
    if ((buffercount = faacDecInit(hDecoder, memmap_buffer + memmap_index,
 
347
        fileread - memmap_index - 1, &samplerate, &channels)) < 0)
 
348
    {
 
349
                MessageBox(mod.hMainWindow, "Error opening input file\n", "FAAD Error", MB_OK);
 
350
                return 1;
 
351
    }
 
352
 
 
353
    memmap_index += buffercount;
 
354
 
 
355
    PlayThread_memmap();
 
356
 
 
357
    return 0;
 
358
}
 
359
 
 
360
int play_file(char *fn)
 
361
{
 
362
    int k;
 
363
    int tagsize;
 
364
 
 
365
    ZeroMemory(buffer, 768*2);
 
366
 
 
367
    infile = open_filestream(fn);
 
368
    
 
369
        if (infile == NULL)
 
370
        return 1;
 
371
 
 
372
    fileread = filelength_filestream(infile);
 
373
 
 
374
    buffercount = bytecount = 0;
 
375
    read_buffer_filestream(infile, buffer, 768*2);
 
376
 
 
377
    tagsize = id3v2_tag(buffer);
 
378
 
 
379
        /* If we find a tag, run right over it */
 
380
    if(tagsize)
 
381
        {
 
382
        if(infile->http)
 
383
        {
 
384
            int i;
 
385
            /* Crude way of doing this, but I believe its fast enough to not make a big difference */
 
386
            close_filestream(infile);
 
387
            infile = open_filestream(fn);
 
388
 
 
389
            for(i=0; i < tagsize; i++)
 
390
                read_byte_filestream(infile);
 
391
        }
 
392
        else
 
393
        {
 
394
            seek_filestream(infile, tagsize, FILE_BEGIN);
 
395
        }
 
396
 
 
397
        bytecount = tagsize;
 
398
        buffercount = 0;
 
399
        read_buffer_filestream(infile, buffer, 768*2);
 
400
    }
 
401
 
 
402
    hDecoder = faacDecOpen();
 
403
 
 
404
        /* Copy the configuration dialog setting and use it as the default */
 
405
        /* initialize the decoder, and get samplerate and channel info */
 
406
 
 
407
    if((buffercount = faacDecInit(hDecoder, buffer, 768*2, &samplerate, &channels)) < 0)
 
408
    {
 
409
                MessageBox(mod.hMainWindow, "Error opening input file\n", "FAAD Error", MB_OK);
 
410
                return 1;
 
411
    }
 
412
 
 
413
    if(buffercount > 0)
 
414
        {
 
415
                bytecount += buffercount;
 
416
 
 
417
                for (k = 0; k < (768*2 - buffercount); k++)
 
418
                        buffer[k] = buffer[k + buffercount];
 
419
 
 
420
                read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
 
421
                buffercount = 0;
 
422
        }
 
423
 
 
424
    PlayThread_file();
 
425
 
 
426
    return 0;
 
427
}
 
428
 
 
429
int play(char *fn)
 
430
{
 
431
    int maxlatency;
 
432
    int thread_id;
 
433
 
 
434
    current_file_mode = m_memmap_file;
 
435
 
 
436
    if (current_file_mode) {
 
437
        if (play_memmap(fn))
 
438
            return -1;
 
439
    } else {
 
440
        if (play_file(fn))
 
441
            return -1;
 
442
    }
 
443
 
 
444
        if(seek_table)
 
445
        {
 
446
                free(seek_table);
 
447
                seek_table = NULL;
 
448
                seek_table_length = 0;
 
449
        }
 
450
 
 
451
        get_AAC_format(fn, &file_info, &seek_table, &seek_table_length, 0);
 
452
 
 
453
        if(infile->http)
 
454
        {
 
455
                /* No seeking in http streams */
 
456
                mod.is_seekable = 0;
 
457
        }
 
458
        else
 
459
        {
 
460
                if (file_info.headertype == 2) /* ADTS header - seekable */
 
461
                        mod.is_seekable = 1;
 
462
                else
 
463
                        mod.is_seekable = 0; /* ADIF or Headerless - not seekable */
 
464
        }
 
465
 
 
466
    strcpy(lastfn,fn);
 
467
    paused=0;
 
468
    decode_pos_ms=0;
 
469
    seek_needed=-1;
 
470
 
 
471
    /*
 
472
      To RageAmp: This is really needed, because aacinfo isn't very accurate on ADIF files yet.
 
473
                  Can be fixed though :-)
 
474
    */
 
475
    file_info.sampling_rate = samplerate;
 
476
    file_info.channels = frameInfo.channels;
 
477
 
 
478
    maxlatency = mod.outMod->Open(file_info.sampling_rate, file_info.channels, 16, -1,-1);
 
479
 
 
480
    if (maxlatency < 0) // error opening device
 
481
    {
 
482
        return -1;
 
483
    }
 
484
 
 
485
    // initialize vis stuff
 
486
    mod.SAVSAInit(maxlatency, file_info.sampling_rate);
 
487
    mod.VSASetInfo(file_info.sampling_rate, file_info.channels);
 
488
 
 
489
    mod.SetInfo(file_info.bitrate/1000, file_info.sampling_rate/1000, file_info.channels,1);
 
490
 
 
491
    mod.outMod->SetVolume(-666); // set the output plug-ins default volume
 
492
 
 
493
    killPlayThread = 0;
 
494
 
 
495
    if((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id)) == NULL)
 
496
    {
 
497
        MessageBox(mod.hMainWindow, "Fatal error: Cannot create playback thread\n", "FAAD Error", MB_OK);
 
498
        return -1;
 
499
    }
 
500
 
 
501
    // Note: This line seriously slows down start up time
 
502
        if(m_priority != 3) // if the priority in config window is set to normal, there is nothing to reset!
 
503
            SetThreadPriority(play_thread_handle, priority_table[m_priority]);
 
504
 
 
505
    return 0;
 
506
}
 
507
 
 
508
void pause() { paused=1; mod.outMod->Pause(1); }
 
509
void unpause() { paused=0; mod.outMod->Pause(0); }
 
510
int ispaused() { return paused; }
 
511
 
 
512
void stop()
 
513
{
 
514
    killPlayThread=1;
 
515
 
 
516
    if (play_thread_handle != INVALID_HANDLE_VALUE)
 
517
    {
 
518
        if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
 
519
            TerminateThread(play_thread_handle,0);
 
520
        CloseHandle(play_thread_handle);
 
521
        play_thread_handle = INVALID_HANDLE_VALUE;
 
522
    }
 
523
 
 
524
    faacDecClose(hDecoder);
 
525
    close_filestream(infile);
 
526
    mod.outMod->Close();
 
527
    mod.SAVSADeInit();
 
528
 
 
529
    if (memmap_buffer) LocalFree(memmap_buffer);
 
530
        if(seek_table)
 
531
        {
 
532
                free(seek_table);
 
533
                seek_table = NULL;
 
534
                seek_table_length = 0;
 
535
        }
 
536
}
 
537
 
 
538
int getlength()
 
539
{
 
540
    return file_info.length;
 
541
}
 
542
 
 
543
int getoutputtime()
 
544
{
 
545
    return decode_pos_ms+(mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime());
 
546
}
 
547
 
 
548
void setoutputtime(int time_in_ms)
 
549
{
 
550
    if (file_info.headertype == 2)
 
551
        seek_needed=time_in_ms;
 
552
    else
 
553
        seek_needed = -1;
 
554
}
 
555
 
 
556
int aac_seek(int pos_ms, int *sktable)
 
557
{
 
558
    double offset_sec;
 
559
 
 
560
    offset_sec = pos_ms / 1000.0;
 
561
    if (!current_file_mode)
 
562
    {
 
563
        seek_filestream(infile, sktable[(int)(offset_sec+0.5)], FILE_BEGIN);
 
564
 
 
565
        bytecount = sktable[(int)(offset_sec+0.5)];
 
566
        buffercount = 0;
 
567
        read_buffer_filestream(infile, buffer, 768*2);
 
568
    } else {
 
569
        memmap_index = sktable[(int)(offset_sec+0.5)];
 
570
    }
 
571
 
 
572
    return 0;
 
573
}
 
574
 
 
575
VOID EnableCheckbox(HWND checkBox, BOOL bEnable, BOOL bChecked)
 
576
{
 
577
    if (bEnable) {
 
578
        EnableWindow(checkBox, TRUE);
 
579
        SendMessage(checkBox, BM_SETCHECK, bChecked?BST_CHECKED:BST_UNCHECKED, 0);
 
580
    } else {
 
581
        EnableWindow(checkBox, FALSE);
 
582
        SendMessage(checkBox, BM_SETCHECK, bChecked?BST_CHECKED:BST_UNCHECKED, 0);
 
583
    }
 
584
}
 
585
 
 
586
void setvolume(int volume) { mod.outMod->SetVolume(volume); }
 
587
void setpan(int pan) { mod.outMod->SetPan(pan); }
 
588
 
 
589
char info_fn[255];
 
590
BOOL bFileChanged;
 
591
 
 
592
BOOL CALLBACK info_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
 
593
{
 
594
    faadAACInfo format;
 
595
    char *tmp_string;
 
596
    char info[1024];
 
597
    LV_COLUMN lvc;
 
598
    BOOL bResult;
 
599
 
 
600
    switch (message) {
 
601
    case WM_INITDIALOG:
 
602
        /* Set up the list control for the ID3 tag */
 
603
        
 
604
        /* Initialize the LV_COLUMN structure. */
 
605
        lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
 
606
        lvc.fmt = LVCFMT_LEFT;
 
607
 
 
608
        /* Add the columns. */
 
609
        lvc.iSubItem = 0;
 
610
        lvc.cx = 100;
 
611
        lvc.pszText = "Frame";
 
612
        ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_ID3LIST), 0, &lvc);
 
613
        lvc.iSubItem = 1;
 
614
        lvc.cx = 250;
 
615
        lvc.pszText = "Data";
 
616
        ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_ID3LIST), 1, &lvc);
 
617
 
 
618
        /* get AAC info */
 
619
        get_AAC_format(info_fn, &format, NULL, NULL, 1);
 
620
 
 
621
        switch(format.headertype)
 
622
        {
 
623
        case 0: /* Headerless */
 
624
            tmp_string = "RAW"; break;
 
625
        case 1: /* ADIF */
 
626
            tmp_string = "ADIF"; break;
 
627
        case 2: /* ADTS */
 
628
            tmp_string = "ADTS"; break;
 
629
        }
 
630
        SetDlgItemText(hwndDlg, IDC_HEADER, tmp_string);
 
631
 
 
632
        if (format.object_type == 0 /* Main */)
 
633
            tmp_string = "Main";
 
634
        else if (format.object_type == 1 /* Low Complexity */)
 
635
            tmp_string = "Low Complexity";
 
636
        else if (format.object_type == 2 /* SSR */)
 
637
            tmp_string = "SSR (unsupported)";
 
638
        else if (format.object_type == 3 /* LTP */)
 
639
            tmp_string = "Main LTP";
 
640
        SetDlgItemText(hwndDlg, IDC_PROFILE, tmp_string);
 
641
 
 
642
        if (format.version == 2) tmp_string = "MPEG2";
 
643
        else tmp_string = "MPEG4";
 
644
        SetDlgItemText(hwndDlg, IDC_VERSION, tmp_string);
 
645
 
 
646
        wsprintf(info, "%d bps", format.bitrate);
 
647
        SetDlgItemText(hwndDlg, IDC_BITRATE, info);
 
648
 
 
649
        wsprintf(info, "%d Hz", format.sampling_rate);
 
650
        SetDlgItemText(hwndDlg, IDC_SAMPLERATE, info);
 
651
 
 
652
        wsprintf(info, "%d ch", format.channels);
 
653
        SetDlgItemText(hwndDlg, IDC_CHANNELS, info);
 
654
 
 
655
        FillID3List(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST), info_fn);
 
656
        if (ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_ID3LIST)) == 0)
 
657
            EnableWindow(GetDlgItem(hwndDlg, IDC_ID3V2TAG), FALSE);
 
658
        else
 
659
            EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), TRUE, TRUE);
 
660
        bFileChanged = FALSE;
 
661
 
 
662
        return TRUE;
 
663
 
 
664
    case WM_NOTIFY:
 
665
        
 
666
        /* Branch depending on the specific notification message. */
 
667
        switch (((LPNMHDR) lParam)->code) { 
 
668
            
 
669
        /* Process LVN_GETDISPINFO to supply information about */
 
670
        /* callback items. */
 
671
        case LVN_GETDISPINFO:
 
672
            List_OnGetDispInfo((LV_DISPINFO *)lParam);
 
673
            break;
 
674
        case NM_DBLCLK:
 
675
            bResult = List_EditData(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST));
 
676
            if (bResult)
 
677
                EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), TRUE, TRUE);
 
678
            bFileChanged = bFileChanged ? bFileChanged : bResult;
 
679
            break;
 
680
        }
 
681
        return TRUE;
 
682
 
 
683
    case WM_COMMAND:
 
684
        switch (LOWORD(wParam)) {
 
685
        case IDC_ADDSTFRAMES:
 
686
            bResult = List_AddStandardFrames(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST));
 
687
            if (bResult)
 
688
                EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), TRUE, TRUE);
 
689
            bFileChanged = bFileChanged ? bFileChanged : bResult;
 
690
            return TRUE;
 
691
        case IDC_ADDFRAME:
 
692
            bResult = List_AddFrame(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST));
 
693
            if (bResult)
 
694
                EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), TRUE, TRUE);
 
695
            bFileChanged = bFileChanged ? bFileChanged : bResult;
 
696
            return TRUE;
 
697
        case IDC_DELFRAME:
 
698
            bResult = List_DeleteSelected(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST));
 
699
            if (ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_ID3LIST)) == 0)
 
700
                EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), FALSE, FALSE);
 
701
            bFileChanged = bFileChanged ? bFileChanged : bResult;
 
702
            return TRUE;
 
703
        case IDC_EDITFRAME:
 
704
            bResult = List_EditData(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST));
 
705
            if (bResult)
 
706
                EnableCheckbox(GetDlgItem(hwndDlg, IDC_ID3V2TAG), TRUE, TRUE);
 
707
            bFileChanged = bFileChanged ? bFileChanged : bResult;
 
708
            return TRUE;
 
709
        case IDC_ID3V2TAG:
 
710
            bFileChanged = TRUE;
 
711
            return TRUE;
 
712
 
 
713
        case IDC_CLOSE:
 
714
        case IDCANCEL:
 
715
            if (bFileChanged == TRUE) {
 
716
                if (MessageBox(hwndDlg, "Save changes?", "Save changes", MB_YESNO) == IDYES)
 
717
                    List_SaveID3(hwndDlg, GetDlgItem(hwndDlg, IDC_ID3LIST), info_fn);
 
718
            }
 
719
            EndDialog(hwndDlg, wParam);
 
720
            return TRUE;
 
721
        }
 
722
    }
 
723
    return FALSE;
 
724
}
 
725
 
 
726
int infoDlg(char *fn, HWND hwnd)
 
727
{
 
728
    lstrcpy(info_fn, fn);
 
729
 
 
730
    DialogBox(mod.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
 
731
        hwnd, info_dialog_proc);
 
732
 
 
733
    return 0;
 
734
}
 
735
 
 
736
LPTSTR PathFindFileName(LPCTSTR pPath)
 
737
{
 
738
    LPCTSTR pT;
 
739
 
 
740
    for (pT = pPath; *pPath; pPath = CharNext(pPath)) {
 
741
        if ((pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) && pPath[1] && (pPath[1] != TEXT('\\')))
 
742
            pT = pPath + 1;
 
743
    }
 
744
 
 
745
    return (LPTSTR)pT;   // const -> non const
 
746
}
 
747
 
 
748
int getsonglength(char *fn)
 
749
{
 
750
    faadAACInfo tmp;
 
751
 
 
752
    get_AAC_format(fn, &tmp, NULL, NULL, 1);
 
753
 
 
754
    return tmp.length;
 
755
}
 
756
 
 
757
void getfileinfo(char *filename, char *title, int *length_in_ms)
 
758
{
 
759
    if (!filename || !*filename)  // currently playing file
 
760
    {
 
761
        if (length_in_ms)
 
762
            *length_in_ms=getlength();
 
763
 
 
764
        if (title)
 
765
            GetID3FileTitle(lastfn, title, m_format_string);
 
766
    }
 
767
    else // some other file
 
768
    {
 
769
        if (length_in_ms)
 
770
            *length_in_ms = getsonglength(filename);
 
771
 
 
772
        if (title)
 
773
            GetID3FileTitle(filename, title, m_format_string);
 
774
    }
 
775
}
 
776
 
 
777
void eq_set(int on, char data[10], int preamp)
 
778
{
 
779
}
 
780
 
 
781
int last_frame;
 
782
 
 
783
int PlayThread_memmap()
 
784
{
 
785
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo,
 
786
        memmap_buffer + memmap_index, fileread - memmap_index - 1);
 
787
    if (frameInfo.error)
 
788
    {
 
789
        MessageBox(NULL, faacDecGetErrorMessage(frameInfo.error), "FAAD Error", MB_OK);
 
790
        last_frame = 1;
 
791
    }
 
792
 
 
793
    memmap_index += frameInfo.bytesconsumed;
 
794
    if (memmap_index >= fileread)
 
795
        last_frame = 1;
 
796
 
 
797
    return frameInfo.bytesconsumed;
 
798
}
 
799
 
 
800
int PlayThread_file()
 
801
{
 
802
    int k;
 
803
 
 
804
    if (buffercount > 0) {
 
805
        for (k = 0; k < (768*2 - buffercount); k++)
 
806
            buffer[k] = buffer[k + buffercount];
 
807
 
 
808
        read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
 
809
        buffercount = 0;
 
810
    }
 
811
 
 
812
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, buffer, 768*2);
 
813
    if (frameInfo.error)
 
814
    {
 
815
        MessageBox(NULL, faacDecGetErrorMessage(frameInfo.error), "FAAD Error", MB_OK);
 
816
        last_frame = 1;
 
817
    }
 
818
 
 
819
    buffercount += frameInfo.bytesconsumed;
 
820
 
 
821
    bytecount += frameInfo.bytesconsumed;
 
822
    if (bytecount >= fileread)
 
823
        last_frame = 1;
 
824
 
 
825
    return frameInfo.bytesconsumed;
 
826
}
 
827
 
 
828
DWORD WINAPI PlayThread(void *b)
 
829
{
 
830
    int done=0;
 
831
    int l;
 
832
        int decoded_frames=0;
 
833
        int br_calc_frames=0;
 
834
        int br_bytes_consumed=0;
 
835
    unsigned long bytesconsumed;
 
836
 
 
837
        PlayThreadAlive = 1;
 
838
    last_frame = 0;
 
839
 
 
840
    while (! *((int *)b) )
 
841
    {
 
842
        if (seek_needed != -1)
 
843
        {
 
844
            int seconds;
 
845
 
 
846
            // Round off to a second
 
847
            seconds = seek_needed - (seek_needed%1000);
 
848
            mod.outMod->Flush(decode_pos_ms);
 
849
            aac_seek(seconds, seek_table);
 
850
            decode_pos_ms = seconds;
 
851
                        seek_needed = -1;
 
852
                        decoded_frames = 0;
 
853
                        br_calc_frames = 0;
 
854
                        br_bytes_consumed = 0;
 
855
        }
 
856
 
 
857
        if (done)
 
858
        {
 
859
            mod.outMod->CanWrite();
 
860
 
 
861
            if (!mod.outMod->IsPlaying())
 
862
            {
 
863
                PostMessage(mod.hMainWindow,WM_WA_AAC_EOF,0,0);
 
864
                PlayThreadAlive = 0;
 
865
                return 0;
 
866
            }
 
867
 
 
868
            Sleep(10);
 
869
        }
 
870
        //assume that max channels is 2.
 
871
        else if (mod.outMod->CanWrite() >= ((1024*file_info.channels*sizeof(short))<<(mod.dsp_isactive()?1:0)))
 
872
        {
 
873
            if(last_frame)
 
874
            {
 
875
                done=1;
 
876
            }
 
877
            else
 
878
            {
 
879
                if (current_file_mode)
 
880
                    bytesconsumed = PlayThread_memmap();
 
881
                else
 
882
                    bytesconsumed = PlayThread_file();
 
883
 
 
884
                                decoded_frames++;
 
885
                                br_calc_frames++;
 
886
                                br_bytes_consumed += bytesconsumed;
 
887
 
 
888
                                /* Update the variable bitrate about every second */
 
889
                                if(m_variable_bitrate_display && br_calc_frames == 43)
 
890
                                {
 
891
                                        int br;
 
892
 
 
893
                                        br = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07));
 
894
 
 
895
                                        mod.SetInfo(br/1000, file_info.sampling_rate/1000, file_info.channels, 1);
 
896
                                        br_calc_frames = 0;
 
897
                                }
 
898
 
 
899
                if (!killPlayThread && (frameInfo.samples > 0))
 
900
                {
 
901
                    mod.SAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms);
 
902
                    mod.VSAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms);
 
903
                    decode_pos_ms+=(1024*1000)/file_info.sampling_rate;
 
904
 
 
905
                    if (mod.dsp_isactive())
 
906
                        l=mod.dsp_dosamples((short *)sample_buffer,frameInfo.samples*sizeof(short)/file_info.channels/(16/8),16,file_info.channels,file_info.sampling_rate)*(file_info.channels*(16/8));
 
907
                    else
 
908
                        l = frameInfo.samples*sizeof(short);
 
909
 
 
910
                    mod.outMod->Write(sample_buffer, l);
 
911
                }
 
912
            }
 
913
        }
 
914
        else
 
915
        {
 
916
            Sleep(10);
 
917
        }
 
918
    }
 
919
 
 
920
        if(seek_table)
 
921
        {
 
922
                free(seek_table);
 
923
                seek_table = NULL;
 
924
                seek_table_length = 0;
 
925
        }
 
926
    
 
927
        PlayThreadAlive = 0;
 
928
        
 
929
    return 0;
 
930
}
 
931
 
 
932
int id3v2_tag(unsigned char *buffer)
 
933
{
 
934
    if (StringComp(buffer, "ID3", 3) == 0)
 
935
        {
 
936
        unsigned long tagsize;
 
937
 
 
938
        /* high bit is not used */
 
939
        tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
 
940
            (buffer[8] <<  7) | (buffer[9] <<  0);
 
941
 
 
942
        tagsize += 10;
 
943
 
 
944
        return tagsize;
 
945
    }
 
946
        else
 
947
        {
 
948
        return 0;
 
949
    }
 
950
}
 
951
 
 
952
In_Module mod =
 
953
{
 
954
    IN_VER,
 
955
    "AudioCoding.com AAC Player: " __DATE__,
 
956
    0,  // hMainWindow
 
957
    0,  // hDllInstance
 
958
    "AAC\0AAC File (*.AAC)\0"
 
959
    ,
 
960
    1, // is_seekable
 
961
    1, // uses output
 
962
    config,
 
963
    about,
 
964
    init,
 
965
    quit,
 
966
    getfileinfo,
 
967
    infoDlg,
 
968
    isourfile,
 
969
    play,
 
970
    pause,
 
971
    unpause,
 
972
    ispaused,
 
973
    stop,
 
974
 
 
975
    getlength,
 
976
    getoutputtime,
 
977
    setoutputtime,
 
978
 
 
979
    setvolume,
 
980
    setpan,
 
981
 
 
982
    0,0,0,0,0,0,0,0,0, // vis stuff
 
983
 
 
984
 
 
985
    0,0, // dsp
 
986
 
 
987
    eq_set,
 
988
 
 
989
    NULL,       // setinfo
 
990
 
 
991
    0 // out_mod
 
992
};
 
993
 
 
994
__declspec( dllexport ) In_Module * winampGetInModule2()
 
995
{
 
996
    return &mod;
 
997
}