~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to extras/faad2/plugins/QCD/QCDFAAD.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello, Mario Limonciello, Martin Hamrle
  • Date: 2008-03-25 20:08:07 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20080325200807-64amsvla1tnnen5s
Tags: 0.8.6.release.e+x264svn20071224+faad2.6.1-0ubuntu1
[ Mario Limonciello ]
* New upstream version. (LP: #206918)
  - New versioning scheme to bring attention to the fact that
    faad and x264 are in the .orig.tar.gz.
  - Fixes 6 CVEs (LP: #196452)
    + CVE: 2007-6681
    + CVE: 2007-6682
    + CVE: 2007-6683
    + CVE: 2008-0295
    + CVE: 2008-0296
* Drop 021_CVE-2008-0984 as it's included upstream.
* debian/rules:
  - Adjust items touched for faad2 when building.
  - Apply all faad2 patches when building
* debian/control:
  - Add dpatch, libfaad-dev, and autotools-dev to build-depends to allow 
    faad2 to build again.
  - Add automake, cvs, and libtool to build depends (now needed for building VLC)

[ Martin Hamrle ]
 * Add new package with pulse output plugin (LP: #196417)
   - debian/patches/030_pulse.diff:
     + patch from upstream trunk to support pulseaudio output
   - debian/rules:
     + enable pulseaudio
   - debian/control:
     + add dependencies to libpulse-dev
     + new package description
   - Creates a NEW binary package, requiring FFe (LP: #204050)

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: QCDFAAD.c,v 1.2 2003/04/28 19:04:35 menno Exp $
20
 
** based on menno's in_faad.dll plugin for Winamp
21
 
**
22
 
** The tag function has been removed because QCD supports ID3v1 & ID3v2 very well
23
 
** About how to tagging: Please read the "ReadMe.txt" first
24
 
**/
25
 
 
26
 
#define WIN32_LEAN_AND_MEAN
27
 
 
28
 
#include <windows.h>
29
 
#include <mmreg.h>
30
 
#include <commctrl.h>
31
 
#include <shellapi.h>
32
 
#include <stdlib.h>
33
 
#include <stdio.h>
34
 
#include "QCDInputDLL.h"
35
 
 
36
 
#include "resource.h"
37
 
 
38
 
#include <faad.h>
39
 
#include <aacinfo.h>
40
 
#include <filestream.h>
41
 
//#include <id3v2tag.h>
42
 
 
43
 
static char app_name[] = "QCDFAAD";
44
 
 
45
 
faadAACInfo file_info;
46
 
 
47
 
faacDecHandle hDecoder;
48
 
faacDecFrameInfo frameInfo;
49
 
 
50
 
HINSTANCE               hInstance;
51
 
HWND                    hwndPlayer, hwndConfig, hwndAbout;
52
 
QCDModInitIn    sQCDCallbacks, *QCDCallbacks;
53
 
BOOL                    oldAPIs = 0;
54
 
static char     lastfn[MAX_PATH]; // currently playing file (used for getting info on the current file)
55
 
int file_length; // file length, in bytes
56
 
int paused; // are we paused?
57
 
int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
58
 
 
59
 
char *sample_buffer; // sample buffer
60
 
unsigned char *buffer; // input buffer
61
 
unsigned char *memmap_buffer; // input buffer for whole file
62
 
long memmap_index;
63
 
 
64
 
long buffercount, fileread, bytecount;
65
 
 
66
 
// seek table for ADTS header files
67
 
unsigned long *seek_table = NULL;
68
 
int seek_table_length=0;
69
 
 
70
 
int killPlayThread = 0; // the kill switch for the decode thread
71
 
HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
72
 
FILE_STREAM *infile;
73
 
 
74
 
/* Function definitions */
75
 
int id3v2_tag(unsigned char *buffer);
76
 
DWORD WINAPI PlayThread(void *b); // the decode thread procedure
77
 
 
78
 
// general funcz
79
 
static void show_error(const char *message,...)
80
 
{
81
 
        char foo[512];
82
 
        va_list args;
83
 
        va_start(args, message);
84
 
        vsprintf(foo, message, args);
85
 
        va_end(args);
86
 
        MessageBox(hwndPlayer, foo, "FAAD Plug-in Error", MB_ICONSTOP);
87
 
}
88
 
 
89
 
 
90
 
// 1= use vbr display, 0 = use average bitrate. This value only controls what shows up in the
91
 
// configuration form. Also- Streaming uses an on-the-fly bitrate display regardless of this value.
92
 
long m_variable_bitrate_display=0;
93
 
long m_priority = 5;
94
 
long m_memmap_file = 0;
95
 
static char INI_FILE[MAX_PATH];
96
 
 
97
 
char *priority_text[] = {       "",
98
 
                                                        "Decode Thread Priority: Lowest",
99
 
                                                        "Decode Thread Priority: Lower",
100
 
                                                        "Decode Thread Priority: Normal",
101
 
                                                        "Decode Thread Priority: Higher",
102
 
                                                        "Decode Thread Priority: Highest (default)"
103
 
                                                };
104
 
 
105
 
long priority_table[] = {0, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST};
106
 
 
107
 
long current_file_mode = 0;
108
 
 
109
 
int PlayThread_memmap();
110
 
int PlayThread_file();
111
 
 
112
 
static void _r_s(char *name,char *data, int mlen)
113
 
{
114
 
        char buf[10];
115
 
        strcpy(buf,data);
116
 
        GetPrivateProfileString(app_name,name,buf,data,mlen,INI_FILE);
117
 
}
118
 
 
119
 
#define RS(x) (_r_s(#x,x,sizeof(x)))
120
 
#define WS(x) (WritePrivateProfileString(app_name,#x,x,INI_FILE))
121
 
 
122
 
void config_read()
123
 
{
124
 
    char variable_bitrate_display[10];
125
 
    char priority[10];
126
 
    char memmap_file[10];
127
 
    char local_buffer_size[10];
128
 
    char stream_buffer_size[10];
129
 
 
130
 
    strcpy(variable_bitrate_display, "1");
131
 
    strcpy(priority, "5");
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(memmap_file);
139
 
    RS(local_buffer_size);
140
 
    RS(stream_buffer_size);
141
 
 
142
 
    m_priority = atoi(priority);
143
 
    m_variable_bitrate_display = atoi(variable_bitrate_display);
144
 
    m_memmap_file = atoi(memmap_file);
145
 
    m_local_buffer_size = atoi(local_buffer_size);
146
 
    m_stream_buffer_size = atoi(stream_buffer_size);
147
 
}
148
 
 
149
 
void config_write()
150
 
{
151
 
    char variable_bitrate_display[10];
152
 
    char priority[10];
153
 
    char memmap_file[10];
154
 
    char local_buffer_size[10];
155
 
    char stream_buffer_size[10];
156
 
 
157
 
    itoa(m_priority, priority, 10);
158
 
    itoa(m_variable_bitrate_display, variable_bitrate_display, 10);
159
 
    itoa(m_memmap_file, memmap_file, 10);
160
 
    itoa(m_local_buffer_size, local_buffer_size, 10);
161
 
    itoa(m_stream_buffer_size, stream_buffer_size, 10);
162
 
 
163
 
    WS(variable_bitrate_display);
164
 
    WS(priority);
165
 
    WS(memmap_file);
166
 
    WS(local_buffer_size);
167
 
    WS(stream_buffer_size);
168
 
}
169
 
 
170
 
//-----------------------------------------------------------------------------
171
 
 
172
 
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID pRes)
173
 
{
174
 
        if (fdwReason == DLL_PROCESS_ATTACH)
175
 
                hInstance = hInst;
176
 
        return TRUE;
177
 
}
178
 
 
179
 
//-----------------------------------------------------------------------------
180
 
//old entrypoint api
181
 
PLUGIN_API BOOL QInputModule(QCDModInitIn *ModInit, QCDModInfo *ModInfo)
182
 
{
183
 
        ModInit->version                                        = PLUGIN_API_VERSION;
184
 
        ModInit->toModule.ShutDown                      = ShutDown;
185
 
        ModInit->toModule.GetTrackExtents       = GetTrackExtents;
186
 
        ModInit->toModule.GetMediaSupported = GetMediaSupported;
187
 
        ModInit->toModule.GetCurrentPosition= GetCurrentPosition;
188
 
        ModInit->toModule.Play                          = Play;
189
 
        ModInit->toModule.Pause                         = Pause;
190
 
        ModInit->toModule.Stop                          = Stop;
191
 
        ModInit->toModule.SetVolume                     = SetVolume;
192
 
        ModInit->toModule.About                         = About;
193
 
        ModInit->toModule.Configure                     = Configure;
194
 
        QCDCallbacks = ModInit;
195
 
 
196
 
        ModInfo->moduleString = "FAAD Plugin v1.0b";
197
 
        /* read config */
198
 
        QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
199
 
 
200
 
        config_read();
201
 
        ModInfo->moduleExtensions = "AAC";
202
 
 
203
 
        hwndPlayer = (HWND)ModInit->Service(opGetParentWnd, 0, 0, 0);
204
 
        lastfn[0] = 0;
205
 
        play_thread_handle = INVALID_HANDLE_VALUE;
206
 
 
207
 
        oldAPIs = 1;
208
 
 
209
 
        return TRUE;
210
 
}
211
 
 
212
 
//-----------------------------------------------------------------------------
213
 
 
214
 
PLUGIN_API QCDModInitIn* INPUTDLL_ENTRY_POINT()
215
 
{
216
 
        sQCDCallbacks.version                                           = PLUGIN_API_VERSION;
217
 
        sQCDCallbacks.toModule.Initialize                       = Initialize;
218
 
        sQCDCallbacks.toModule.ShutDown                         = ShutDown;
219
 
        sQCDCallbacks.toModule.GetTrackExtents          = GetTrackExtents;
220
 
        sQCDCallbacks.toModule.GetMediaSupported        = GetMediaSupported;
221
 
        sQCDCallbacks.toModule.GetCurrentPosition       = GetCurrentPosition;
222
 
        sQCDCallbacks.toModule.Play                                     = Play;
223
 
        sQCDCallbacks.toModule.Pause                            = Pause;
224
 
        sQCDCallbacks.toModule.Stop                                     = Stop;
225
 
        sQCDCallbacks.toModule.SetVolume                        = SetVolume;
226
 
        sQCDCallbacks.toModule.About                            = About;
227
 
        sQCDCallbacks.toModule.Configure                        = Configure;
228
 
 
229
 
        QCDCallbacks = &sQCDCallbacks;
230
 
        return &sQCDCallbacks;
231
 
}
232
 
 
233
 
//----------------------------------------------------------------------------
234
 
 
235
 
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
236
 
{
237
 
        char tmp[10];
238
 
 
239
 
    switch (message)
240
 
        {
241
 
    case WM_INITDIALOG:
242
 
        /* Set priority slider range and previous position */
243
 
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(1, 5)); 
244
 
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, m_priority);
245
 
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
246
 
                
247
 
                /* Put a limit to the amount of characters allowed in the buffer boxes */
248
 
                SendMessage(GetDlgItem(hwndDlg, LOCAL_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
249
 
                SendMessage(GetDlgItem(hwndDlg, STREAM_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
250
 
 
251
 
            if(m_variable_bitrate_display)
252
 
                        SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0);
253
 
            if(m_memmap_file)
254
 
                        SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_CHECKED, 0);
255
 
 
256
 
                itoa(m_local_buffer_size, tmp, 10);
257
 
                SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp);
258
 
 
259
 
                itoa(m_stream_buffer_size, tmp, 10);
260
 
                SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp);
261
 
 
262
 
                return TRUE;
263
 
 
264
 
        case WM_HSCROLL:
265
 
 
266
 
                /* Thread priority slider moved */
267
 
                if(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER) == (HWND) lParam)
268
 
                {
269
 
                        int tmp;
270
 
                        tmp = SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_GETPOS, 0, 0);
271
 
 
272
 
                        if(tmp > 0)
273
 
                        {
274
 
                                m_priority = tmp;
275
 
 
276
 
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
277
 
 
278
 
                                if(play_thread_handle)
279
 
                                        SetThreadPriority(play_thread_handle, priority_table[m_priority]);
280
 
                        }
281
 
                }
282
 
 
283
 
                return TRUE;
284
 
 
285
 
    case WM_COMMAND:
286
 
 
287
 
                if(HIWORD(wParam) == BN_CLICKED)
288
 
                {
289
 
                        if(GetDlgItem(hwndDlg, VARBITRATE_CHK) == (HWND) lParam)
290
 
                        {
291
 
                                /* Variable Bitrate checkbox hit */
292
 
                                m_variable_bitrate_display = SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_GETCHECK, 0, 0); 
293
 
                        }
294
 
                        if(GetDlgItem(hwndDlg, IDC_MEMMAP) == (HWND) lParam)
295
 
                        {
296
 
                                /* Variable Bitrate checkbox hit */
297
 
                                m_memmap_file = SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_GETCHECK, 0, 0); 
298
 
                        }
299
 
                }
300
 
 
301
 
        switch (LOWORD(wParam))
302
 
                {
303
 
                        case OK_BTN:
304
 
                                /* User hit OK, save buffer settings (all others are set on command) */
305
 
                                GetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp, 5);
306
 
                                m_local_buffer_size = atol(tmp);
307
 
 
308
 
                                GetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp, 5);
309
 
                                m_stream_buffer_size = atol(tmp);
310
 
 
311
 
                config_write();
312
 
 
313
 
                                EndDialog(hwndDlg, wParam);
314
 
                                return TRUE;
315
 
                        case RESET_BTN:
316
 
                                SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0);
317
 
                                m_variable_bitrate_display = 1;
318
 
                                SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_UNCHECKED, 0);
319
 
                                m_memmap_file = 0;
320
 
                                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, 5);
321
 
                                m_priority = 5;
322
 
                                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[5]);
323
 
                                SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, "128");
324
 
                                m_local_buffer_size = 128;
325
 
                                SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, "64");
326
 
                                m_stream_buffer_size = 64;
327
 
                                return TRUE;
328
 
                        case IDCANCEL:
329
 
                        case CANCEL_BTN:
330
 
                                /* User hit Cancel or the X, just close without saving buffer settings */
331
 
                                DestroyWindow(hwndDlg);
332
 
                                return TRUE;
333
 
        }
334
 
    }
335
 
    return FALSE;
336
 
}
337
 
 
338
 
 
339
 
void Configure(int flags)
340
 
{
341
 
        if(!IsWindow(hwndConfig))
342
 
                hwndConfig = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG), hwndPlayer, config_dialog_proc);
343
 
        ShowWindow(hwndConfig, SW_NORMAL);
344
 
}
345
 
 
346
 
//-----------------------------------------------------------------------------
347
 
// proc of "About Dialog"
348
 
INT_PTR CALLBACK about_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
349
 
{
350
 
        static RECT rcLOGO, rcMail1, rcMail2/*, rcMail3*/;
351
 
        POINT ptMouse;
352
 
        static char szPluginVer[] = "QCD FAAD Input Plug-in v1.0b\nCompiled on " __TIME__ ", " __DATE__;
353
 
        static char szFLACVer[] = "Using: FAAD2 v "FAAD2_VERSION" by";
354
 
 
355
 
        switch (uMsg)
356
 
        {
357
 
        case WM_INITDIALOG:
358
 
        case WM_MOVE:
359
 
                GetWindowRect(GetDlgItem(hwndDlg, IDC_LOGO), &rcLOGO);
360
 
                GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL1), &rcMail1);
361
 
                GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail2);
362
 
//              GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail3);
363
 
 
364
 
                SetDlgItemText(hwndDlg, IDC_PLUGINVER, szPluginVer);
365
 
                SetDlgItemText(hwndDlg, IDC_FAADVER, szFLACVer);
366
 
                
367
 
                return TRUE;
368
 
        case WM_MOUSEMOVE:
369
 
                ptMouse.x = LOWORD(lParam);
370
 
                ptMouse.y = HIWORD(lParam);
371
 
                ClientToScreen(hwndDlg, &ptMouse);
372
 
                if( (ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
373
 
                        ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom) 
374
 
                        ||
375
 
                        (ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
376
 
                        ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom) 
377
 
                        ||
378
 
                        (ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
379
 
                        ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom) 
380
 
/*                      ||
381
 
                        (ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
382
 
                        ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)*/ )
383
 
                        SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(32649)));
384
 
                else
385
 
                        SetCursor(LoadCursor(NULL, IDC_ARROW));
386
 
 
387
 
                return TRUE;
388
 
        case WM_LBUTTONDOWN:
389
 
                ptMouse.x = LOWORD(lParam);
390
 
                ptMouse.y = HIWORD(lParam);
391
 
                ClientToScreen(hwndDlg, &ptMouse);
392
 
                if(ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
393
 
                        ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom)
394
 
                        ShellExecute(0, NULL, "http://www.audiocoding.com", NULL,NULL, SW_NORMAL);
395
 
                else if(ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
396
 
                        ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom)
397
 
                        ShellExecute(0, NULL, "mailto:shaohao@elong.com", NULL,NULL, SW_NORMAL);
398
 
                else if(ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
399
 
                        ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom)
400
 
                        ShellExecute(0, NULL, "mailto:menno@audiocoding.com", NULL,NULL, SW_NORMAL);
401
 
/*              else if(ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
402
 
                        ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)
403
 
                        ShellExecute(0, NULL, "I don't know", NULL,NULL, SW_NORMAL);
404
 
*/
405
 
                return TRUE;
406
 
        case WM_COMMAND:
407
 
                switch(LOWORD(wParam))
408
 
                {
409
 
                case IDOK:
410
 
                default:
411
 
                        DestroyWindow(hwndDlg);
412
 
                        return TRUE;
413
 
                }
414
 
        }
415
 
        return FALSE;
416
 
}
417
 
 
418
 
void About(int flags)
419
 
{
420
 
        if(!IsWindow(hwndAbout))
421
 
                hwndAbout = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwndPlayer, about_dialog_proc); 
422
 
        ShowWindow(hwndAbout, SW_SHOW);
423
 
}
424
 
 
425
 
//-----------------------------------------------------------------------------
426
 
 
427
 
BOOL Initialize(QCDModInfo *ModInfo, int flags)
428
 
{
429
 
        hwndPlayer = (HWND)QCDCallbacks->Service(opGetParentWnd, 0, 0, 0);
430
 
 
431
 
        lastfn[0] = 0;
432
 
        seek_needed = -1;
433
 
        paused = 0;
434
 
        play_thread_handle = INVALID_HANDLE_VALUE;
435
 
 
436
 
        /* read config */
437
 
        QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
438
 
    config_read();
439
 
 
440
 
        ModInfo->moduleString = "FAAD Plugin v1.0b";
441
 
        ModInfo->moduleExtensions = "AAC";
442
 
 
443
 
    /* Initialize winsock, necessary for streaming */
444
 
    WinsockInit();
445
 
 
446
 
        // insert menu item into plugin menu
447
 
//      QCDCallbacks->Service(opSetPluginMenuItem, hInstance, IDD_CONFIG, (long)"FAAD Plug-in");
448
 
 
449
 
        return TRUE;
450
 
}
451
 
 
452
 
//----------------------------------------------------------------------------
453
 
 
454
 
void ShutDown(int flags)
455
 
{
456
 
        Stop(lastfn, STOPFLAG_FORCESTOP);
457
 
 
458
 
    if(buffer)
459
 
                LocalFree(buffer);
460
 
 
461
 
    /* Deallocate winsock */
462
 
    WinsockDeInit();
463
 
 
464
 
        // delete the inserted plugin menu
465
 
//      QCDCallbacks->Service(opSetPluginMenuItem, hInstance, 0, 0);
466
 
}
467
 
 
468
 
//-----------------------------------------------------------------------------
469
 
 
470
 
BOOL GetMediaSupported(LPCSTR medianame, MediaInfo *mediaInfo)
471
 
{
472
 
        FILE_STREAM *in;
473
 
        faadAACInfo tmp;
474
 
        char *ch = strrchr(medianame, '.');
475
 
 
476
 
        if (!medianame || !*medianame)
477
 
                return FALSE;
478
 
 
479
 
        if(!ch)
480
 
                return (lstrlen(medianame) > 2); // no extension defaults to me (if not drive letter)
481
 
 
482
 
   /* Finally fixed */
483
 
    if(StringComp(ch, ".aac", 4) == 0)
484
 
    {
485
 
                in = open_filestream((char *)medianame);
486
 
                
487
 
                if(in != NULL && mediaInfo)
488
 
                {
489
 
                        if(in->http)
490
 
                        {
491
 
                                /* No seeking in http streams */
492
 
                                mediaInfo->mediaType = DIGITAL_STREAM_MEDIA;
493
 
                                mediaInfo->op_canSeek = FALSE;
494
 
                        }
495
 
                        else
496
 
                        {
497
 
                                mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
498
 
                            get_AAC_format((char *)medianame, &tmp, NULL, NULL, 1);
499
 
                                if(tmp.headertype == 2) /* ADTS header - seekable */
500
 
                                        mediaInfo->op_canSeek = TRUE;
501
 
                                else
502
 
                                        mediaInfo->op_canSeek = FALSE; /* ADIF or Headerless - not seekable */
503
 
                        }
504
 
                        
505
 
                        close_filestream(in);
506
 
                        return TRUE;
507
 
                }
508
 
                else
509
 
                {
510
 
                        close_filestream(in);
511
 
                        return FALSE;
512
 
                }
513
 
        }
514
 
        else
515
 
                return FALSE;           
516
 
}
517
 
 
518
 
unsigned long samplerate, channels;
519
 
 
520
 
int play_memmap(char *fn)
521
 
{
522
 
    int tagsize = 0;
523
 
 
524
 
    infile = open_filestream(fn);
525
 
    
526
 
        if (infile == NULL)
527
 
        return 1;
528
 
 
529
 
    fileread = filelength_filestream(infile);
530
 
 
531
 
    memmap_buffer = (char*)LocalAlloc(LPTR, fileread);
532
 
    read_buffer_filestream(infile, memmap_buffer, fileread);
533
 
 
534
 
    /* skip id3v2 tag */
535
 
    memmap_index = id3v2_tag(memmap_buffer);
536
 
 
537
 
    hDecoder = faacDecOpen();
538
 
 
539
 
        /* Copy the configuration dialog setting and use it as the default */
540
 
        /* initialize the decoder, and get samplerate and channel info */
541
 
 
542
 
    if( (buffercount = faacDecInit(hDecoder, memmap_buffer + memmap_index,
543
 
        fileread - memmap_index - 1, &samplerate, &channels)) < 0 )
544
 
    {
545
 
                show_error("Error opening input file");
546
 
                return 1;
547
 
    }
548
 
 
549
 
    memmap_index += buffercount;
550
 
 
551
 
    PlayThread_memmap();
552
 
 
553
 
    return 0;
554
 
}
555
 
 
556
 
int play_file(char *fn)
557
 
{
558
 
    int k;
559
 
    int tagsize;
560
 
 
561
 
    ZeroMemory(buffer, 768*2);
562
 
 
563
 
     infile = open_filestream(fn);
564
 
    
565
 
        if (infile == NULL)
566
 
        return 1;
567
 
 
568
 
        fileread = filelength_filestream(infile);
569
 
 
570
 
    buffercount = bytecount = 0;
571
 
    read_buffer_filestream(infile, buffer, 768*2);
572
 
 
573
 
    tagsize = id3v2_tag(buffer);
574
 
 
575
 
        /* If we find a tag, run right over it */
576
 
    if(tagsize)
577
 
        {
578
 
        if(infile->http)
579
 
        {
580
 
            int i;
581
 
            /* Crude way of doing this, but I believe its fast enough to not make a big difference */
582
 
            close_filestream(infile);
583
 
            infile = open_filestream(fn);
584
 
 
585
 
            for(i=0; i < tagsize; i++)
586
 
                read_byte_filestream(infile);
587
 
        }
588
 
        else
589
 
            seek_filestream(infile, tagsize, FILE_BEGIN);
590
 
 
591
 
        bytecount = tagsize;
592
 
        buffercount = 0;
593
 
        read_buffer_filestream(infile, buffer, 768*2);
594
 
    }
595
 
 
596
 
    hDecoder = faacDecOpen();
597
 
 
598
 
        /* Copy the configuration dialog setting and use it as the default */
599
 
        /* initialize the decoder, and get samplerate and channel info */
600
 
 
601
 
    if((buffercount = faacDecInit(hDecoder, buffer, 768*2, &samplerate, &channels)) < 0)
602
 
    {
603
 
                show_error("Error opening input file");
604
 
                return 1;
605
 
    }
606
 
 
607
 
    if(buffercount > 0)
608
 
        {
609
 
                bytecount += buffercount;
610
 
 
611
 
                for (k = 0; k < (768*2 - buffercount); k++)
612
 
                        buffer[k] = buffer[k + buffercount];
613
 
 
614
 
                read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
615
 
                buffercount = 0;
616
 
        }
617
 
 
618
 
    PlayThread_file();
619
 
 
620
 
    return 0;
621
 
}
622
 
 
623
 
 
624
 
//-----------------------------------------------------------------------------
625
 
 
626
 
BOOL Play(LPCSTR medianame, int playfrom, int playto, int flags)
627
 
{
628
 
        if(stricmp(lastfn, medianame) != 0)
629
 
        {
630
 
                sQCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
631
 
                Stop(lastfn, STOPFLAG_PLAYDONE);
632
 
        }
633
 
 
634
 
        if(paused)
635
 
        {
636
 
                // Update the player controls to reflect the new unpaused state
637
 
                sQCDCallbacks.toPlayer.OutputPause(0);
638
 
 
639
 
                Pause(medianame, PAUSE_DISABLED);
640
 
 
641
 
                if (playfrom >= 0)
642
 
                        seek_needed = playfrom;
643
 
        }
644
 
        else if(play_thread_handle != INVALID_HANDLE_VALUE)
645
 
        {
646
 
                seek_needed = playfrom;
647
 
                return TRUE;
648
 
        }
649
 
        else
650
 
        {
651
 
                int thread_id;
652
 
 
653
 
                // alloc the input buffer
654
 
                buffer = (unsigned char*)LocalAlloc(LPTR, 768*2);
655
 
 
656
 
                current_file_mode = m_memmap_file;
657
 
                
658
 
                if(current_file_mode)
659
 
                {
660
 
                        if(play_memmap((char *)medianame))
661
 
                                return FALSE;
662
 
                }
663
 
                else
664
 
                {
665
 
                        if(play_file((char *)medianame))
666
 
                                return FALSE;
667
 
                }
668
 
                
669
 
                if(seek_table)
670
 
                {
671
 
                        free(seek_table);
672
 
                        seek_table = NULL;
673
 
                        seek_table_length = 0;
674
 
                }
675
 
                
676
 
                get_AAC_format((char *)medianame, &file_info, &seek_table, &seek_table_length, 0);
677
 
                
678
 
                seek_needed = playfrom > 0 ? playfrom : -1;
679
 
                killPlayThread = 0;
680
 
                strcpy(lastfn,medianame);
681
 
 
682
 
                /*
683
 
                To RageAmp: This is really needed, because aacinfo isn't very accurate on ADIF files yet.
684
 
                Can be fixed though :-)
685
 
                */
686
 
                file_info.sampling_rate = samplerate;
687
 
                file_info.channels = frameInfo.channels;
688
 
 
689
 
                play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id);
690
 
                if(!play_thread_handle)
691
 
                        return FALSE;
692
 
                
693
 
                // Note: This line seriously slows down start up time
694
 
                if(m_priority != 3) // if the priority in config window is set to normal, there is nothing to reset!
695
 
                        SetThreadPriority(play_thread_handle, priority_table[m_priority]);
696
 
                
697
 
    }
698
 
 
699
 
        return TRUE;
700
 
}
701
 
 
702
 
//-----------------------------------------------------------------------------
703
 
 
704
 
BOOL Pause(LPCSTR medianame, int flags)
705
 
{
706
 
        if(QCDCallbacks->toPlayer.OutputPause(flags))
707
 
        {
708
 
                // send back pause/unpause notification
709
 
                QCDCallbacks->toPlayer.PlayPaused(medianame, flags);
710
 
                paused = flags;
711
 
                return TRUE;
712
 
        }
713
 
        return FALSE;
714
 
}
715
 
 
716
 
//-----------------------------------------------------------------------------
717
 
 
718
 
BOOL Stop(LPCSTR medianame, int flags)
719
 
{
720
 
        if(medianame && *medianame && stricmp(lastfn, medianame) == 0)
721
 
        {
722
 
                sQCDCallbacks.toPlayer.OutputStop(flags);
723
 
                
724
 
                killPlayThread = 1;
725
 
                if(play_thread_handle != INVALID_HANDLE_VALUE)
726
 
                {
727
 
                        if(WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
728
 
                        {
729
 
//                              MessageBox(hwndPlayer, "FAAD thread kill timeout", "debug", 0);
730
 
                                TerminateThread(play_thread_handle,0);
731
 
                        }
732
 
                        CloseHandle(play_thread_handle);
733
 
                        play_thread_handle = INVALID_HANDLE_VALUE;
734
 
                }
735
 
 
736
 
                if (oldAPIs)
737
 
                        QCDCallbacks->toPlayer.PlayStopped(lastfn);
738
 
                
739
 
                lastfn[0] = 0;
740
 
        }
741
 
 
742
 
        return TRUE;
743
 
}
744
 
 
745
 
int aac_seek(int pos_ms, int *sktable)
746
 
{
747
 
    double offset_sec;
748
 
 
749
 
    offset_sec = pos_ms / 1000.0;
750
 
    if(!current_file_mode)
751
 
    {
752
 
        seek_filestream(infile, sktable[(int)(offset_sec+0.5)], FILE_BEGIN);
753
 
 
754
 
        bytecount = sktable[(int)(offset_sec+0.5)];
755
 
        buffercount = 0;
756
 
        read_buffer_filestream(infile, buffer, 768*2);
757
 
    }
758
 
        else
759
 
        {
760
 
        memmap_index = sktable[(int)(offset_sec+0.5)];
761
 
    }
762
 
 
763
 
    return 0;
764
 
}
765
 
 
766
 
//-----------------------------------------------------------------------------
767
 
 
768
 
void SetVolume(int levelleft, int levelright, int flags)
769
 
{
770
 
        QCDCallbacks->toPlayer.OutputSetVol(levelleft, levelright, flags);
771
 
}
772
 
 
773
 
//-----------------------------------------------------------------------------
774
 
 
775
 
BOOL GetCurrentPosition(LPCSTR medianame, long *track, long *offset)
776
 
{
777
 
        return QCDCallbacks->toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
778
 
}
779
 
 
780
 
//-----------------------------------------------------------------------------
781
 
 
782
 
BOOL GetTrackExtents(LPCSTR medianame, TrackExtents *ext, int flags)
783
 
{
784
 
    faadAACInfo tmp;
785
 
 
786
 
    if(get_AAC_format((char*)medianame, &tmp, NULL, NULL, 1))
787
 
                return FALSE;
788
 
 
789
 
        ext->track = 1;
790
 
        ext->start = 0;
791
 
        ext->end = tmp.length;
792
 
        ext->bytesize = tmp.bitrate * tmp.length;
793
 
        ext->unitpersec = 1000;
794
 
 
795
 
        return TRUE;
796
 
}
797
 
 
798
 
//--------------------------for play thread-------------------------------------
799
 
 
800
 
int last_frame;
801
 
 
802
 
DWORD WINAPI PlayThread(void *b)
803
 
{
804
 
    BOOL done = FALSE, updatePos = FALSE;
805
 
        int decode_pos_ms = 0; // current decoding position, in milliseconds
806
 
    int l;
807
 
        int decoded_frames=0;
808
 
        int br_calc_frames=0;
809
 
        int br_bytes_consumed=0;
810
 
    unsigned long bytesconsumed;
811
 
 
812
 
    last_frame = 0;
813
 
 
814
 
        if(!done)
815
 
        {
816
 
                // open outputdevice
817
 
                WAVEFORMATEX wf;
818
 
                wf.wFormatTag = WAVE_FORMAT_PCM;
819
 
                wf.cbSize = 0;
820
 
                wf.nChannels = file_info.channels;
821
 
                wf.wBitsPerSample = 16;
822
 
                wf.nSamplesPerSec = file_info.sampling_rate;
823
 
                wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
824
 
                wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
825
 
                if (!QCDCallbacks->toPlayer.OutputOpen(lastfn, &wf))
826
 
                {
827
 
                        show_error("Error: Failed openning output plugin!");
828
 
                        done = TRUE; // cannot open sound device
829
 
                }
830
 
        }
831
 
 
832
 
    while (! *((int *)b) )
833
 
    {
834
 
                /********************** SEEK ************************/
835
 
       if (!done && seek_needed >= 0)
836
 
           {
837
 
            int seconds;
838
 
 
839
 
            // Round off to a second
840
 
            seconds = seek_needed - (seek_needed%1000);
841
 
                        QCDCallbacks->toPlayer.OutputFlush(decode_pos_ms);
842
 
            aac_seek(seconds, seek_table);
843
 
            decode_pos_ms = seconds;
844
 
                        decoded_frames = 0;
845
 
                        br_calc_frames = 0;
846
 
                        br_bytes_consumed = 0;
847
 
 
848
 
                        seek_needed = -1;
849
 
                        updatePos = 1;
850
 
           }
851
 
 
852
 
                /********************* QUIT *************************/
853
 
                if (done)
854
 
                {
855
 
                        if (QCDCallbacks->toPlayer.OutputDrain(0) && !(seek_needed >= 0))
856
 
                        {
857
 
                                play_thread_handle = INVALID_HANDLE_VALUE;
858
 
                                QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE);
859
 
                                QCDCallbacks->toPlayer.PlayDone(lastfn);
860
 
                        }
861
 
                        else if (seek_needed >= 0)
862
 
                        {
863
 
                                done = FALSE;
864
 
                                continue;
865
 
                        }
866
 
                        break;
867
 
                }
868
 
 
869
 
        /******************* DECODE TO BUFFER ****************/
870
 
                else
871
 
        {
872
 
                        if (current_file_mode)
873
 
                                bytesconsumed = PlayThread_memmap();
874
 
                        else
875
 
                                bytesconsumed = PlayThread_file();
876
 
 
877
 
                        if(last_frame)
878
 
                                done = TRUE;
879
 
                        else
880
 
                        {
881
 
 
882
 
                                decoded_frames++;
883
 
                                br_calc_frames++;
884
 
                                br_bytes_consumed += bytesconsumed;
885
 
 
886
 
                                /* Update the variable bitrate about every second */
887
 
                                if(m_variable_bitrate_display && br_calc_frames == 43)
888
 
                                {
889
 
                                        AudioInfo vai;
890
 
                                        vai.struct_size = sizeof(AudioInfo);
891
 
                                        vai.frequency = file_info.sampling_rate;
892
 
                                        vai.bitrate = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07));
893
 
                                        vai.mode = (channels == 2) ? 0 : 3;
894
 
                                        vai.layer = 0;
895
 
                                        vai.level = file_info.version;
896
 
                                        QCDCallbacks->Service(opSetAudioInfo, &vai, sizeof(AudioInfo), 0);
897
 
 
898
 
                                        br_calc_frames = 0;
899
 
                                }
900
 
 
901
 
                if (!killPlayThread && (frameInfo.samples > 0))
902
 
                {
903
 
                    //update the time display
904
 
                                        if (updatePos)
905
 
                                        {
906
 
                                                QCDCallbacks->toPlayer.PositionUpdate(decode_pos_ms);
907
 
                                                updatePos = 0;
908
 
                                        }
909
 
                                        
910
 
                                        {
911
 
                                                WriteDataStruct wd;
912
 
 
913
 
                                                l = frameInfo.samples * sizeof(short);
914
 
 
915
 
                                                decode_pos_ms += (1024*1000)/file_info.sampling_rate;
916
 
                                                
917
 
                                                wd.bytelen = l;
918
 
                                                wd.data = sample_buffer;
919
 
                                                wd.markerend = 0;
920
 
                                                wd.markerstart = decode_pos_ms;
921
 
                                                wd.bps = 16;
922
 
                                                wd.nch = frameInfo.channels;
923
 
                                                wd.numsamples =l/file_info.channels/(16/8);
924
 
                                                wd.srate = file_info.sampling_rate;
925
 
                                                
926
 
                                                if (!QCDCallbacks->toPlayer.OutputWrite(&wd))
927
 
                                                        done = TRUE;
928
 
                                        }
929
 
                                }
930
 
                        }
931
 
                }
932
 
        Sleep(10);
933
 
    }
934
 
 
935
 
        // close up
936
 
        play_thread_handle = INVALID_HANDLE_VALUE;
937
 
 
938
 
        faacDecClose(hDecoder);
939
 
        hDecoder = INVALID_HANDLE_VALUE;
940
 
        close_filestream(infile);
941
 
        infile = NULL;
942
 
 
943
 
        if(seek_table)
944
 
        {
945
 
                free(seek_table);
946
 
                seek_table = NULL;
947
 
                seek_table_length = 0;
948
 
        }
949
 
 
950
 
        if(buffer)
951
 
        {
952
 
                LocalFree(buffer);
953
 
                buffer = NULL;
954
 
        }
955
 
        if(memmap_buffer)
956
 
        {
957
 
                LocalFree(memmap_buffer);
958
 
                memmap_buffer = NULL;
959
 
        }
960
 
 
961
 
    return 0;
962
 
}
963
 
 
964
 
// thread play funcs
965
 
int PlayThread_memmap()
966
 
{
967
 
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo,
968
 
        memmap_buffer + memmap_index, fileread - memmap_index - 1);
969
 
    if (frameInfo.error)
970
 
    {
971
 
//        show_error(faacDecGetErrorMessage(frameInfo.error));
972
 
        last_frame = 1;
973
 
    }
974
 
 
975
 
    memmap_index += frameInfo.bytesconsumed;
976
 
    if (memmap_index >= fileread)
977
 
        last_frame = 1;
978
 
 
979
 
    return frameInfo.bytesconsumed;
980
 
}
981
 
 
982
 
int PlayThread_file()
983
 
{
984
 
    int k;
985
 
 
986
 
    if (buffercount > 0)
987
 
        {
988
 
        for (k = 0; k < (768*2 - buffercount); k++)
989
 
            buffer[k] = buffer[k + buffercount];
990
 
 
991
 
        read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
992
 
        buffercount = 0;
993
 
    }
994
 
 
995
 
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, buffer, 768*2);
996
 
    if (frameInfo.error)
997
 
    {
998
 
//        show_error(faacDecGetErrorMessage(frameInfo.error));
999
 
        last_frame = 1;
1000
 
    }
1001
 
 
1002
 
    buffercount += frameInfo.bytesconsumed;
1003
 
 
1004
 
    bytecount += frameInfo.bytesconsumed;
1005
 
    if (bytecount >= fileread)
1006
 
        last_frame = 1;
1007
 
 
1008
 
    return frameInfo.bytesconsumed;
1009
 
}
1010
 
 
1011
 
// tag
1012
 
int id3v2_tag(unsigned char *buffer)
1013
 
{
1014
 
    if (StringComp(buffer, "ID3", 3) == 0)
1015
 
        {
1016
 
        unsigned long tagsize;
1017
 
 
1018
 
        /* high bit is not used */
1019
 
        tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
1020
 
            (buffer[8] <<  7) | (buffer[9] <<  0);
1021
 
 
1022
 
        tagsize += 10;
1023
 
 
1024
 
        return tagsize;
1025
 
    }
1026
 
        else
1027
 
        {
1028
 
        return 0;
1029
 
    }
 
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: QCDFAAD.c,v 1.2 2003/04/28 19:04:35 menno Exp $
 
20
** based on menno's in_faad.dll plugin for Winamp
 
21
**
 
22
** The tag function has been removed because QCD supports ID3v1 & ID3v2 very well
 
23
** About how to tagging: Please read the "ReadMe.txt" first
 
24
**/
 
25
 
 
26
#define WIN32_LEAN_AND_MEAN
 
27
 
 
28
#include <windows.h>
 
29
#include <mmreg.h>
 
30
#include <commctrl.h>
 
31
#include <shellapi.h>
 
32
#include <stdlib.h>
 
33
#include <stdio.h>
 
34
#include "QCDInputDLL.h"
 
35
 
 
36
#include "resource.h"
 
37
 
 
38
#include <faad.h>
 
39
#include <aacinfo.h>
 
40
#include <filestream.h>
 
41
//#include <id3v2tag.h>
 
42
 
 
43
static char app_name[] = "QCDFAAD";
 
44
 
 
45
faadAACInfo file_info;
 
46
 
 
47
faacDecHandle hDecoder;
 
48
faacDecFrameInfo frameInfo;
 
49
 
 
50
HINSTANCE               hInstance;
 
51
HWND                    hwndPlayer, hwndConfig, hwndAbout;
 
52
QCDModInitIn    sQCDCallbacks, *QCDCallbacks;
 
53
BOOL                    oldAPIs = 0;
 
54
static char     lastfn[MAX_PATH]; // currently playing file (used for getting info on the current file)
 
55
int file_length; // file length, in bytes
 
56
int paused; // are we paused?
 
57
int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
 
58
 
 
59
char *sample_buffer; // sample buffer
 
60
unsigned char *buffer; // input buffer
 
61
unsigned char *memmap_buffer; // input buffer for whole file
 
62
long memmap_index;
 
63
 
 
64
long buffercount, fileread, bytecount;
 
65
 
 
66
// seek table for ADTS header files
 
67
unsigned long *seek_table = NULL;
 
68
int seek_table_length=0;
 
69
 
 
70
int killPlayThread = 0; // the kill switch for the decode thread
 
71
HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
 
72
FILE_STREAM *infile;
 
73
 
 
74
/* Function definitions */
 
75
int id3v2_tag(unsigned char *buffer);
 
76
DWORD WINAPI PlayThread(void *b); // the decode thread procedure
 
77
 
 
78
// general funcz
 
79
static void show_error(const char *message,...)
 
80
{
 
81
        char foo[512];
 
82
        va_list args;
 
83
        va_start(args, message);
 
84
        vsprintf(foo, message, args);
 
85
        va_end(args);
 
86
        MessageBox(hwndPlayer, foo, "FAAD Plug-in Error", MB_ICONSTOP);
 
87
}
 
88
 
 
89
 
 
90
// 1= use vbr display, 0 = use average bitrate. This value only controls what shows up in the
 
91
// configuration form. Also- Streaming uses an on-the-fly bitrate display regardless of this value.
 
92
long m_variable_bitrate_display=0;
 
93
long m_priority = 5;
 
94
long m_memmap_file = 0;
 
95
static char INI_FILE[MAX_PATH];
 
96
 
 
97
char *priority_text[] = {       "",
 
98
                                                        "Decode Thread Priority: Lowest",
 
99
                                                        "Decode Thread Priority: Lower",
 
100
                                                        "Decode Thread Priority: Normal",
 
101
                                                        "Decode Thread Priority: Higher",
 
102
                                                        "Decode Thread Priority: Highest (default)"
 
103
                                                };
 
104
 
 
105
long priority_table[] = {0, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST};
 
106
 
 
107
long current_file_mode = 0;
 
108
 
 
109
int PlayThread_memmap();
 
110
int PlayThread_file();
 
111
 
 
112
static void _r_s(char *name,char *data, int mlen)
 
113
{
 
114
        char buf[10];
 
115
        strcpy(buf,data);
 
116
        GetPrivateProfileString(app_name,name,buf,data,mlen,INI_FILE);
 
117
}
 
118
 
 
119
#define RS(x) (_r_s(#x,x,sizeof(x)))
 
120
#define WS(x) (WritePrivateProfileString(app_name,#x,x,INI_FILE))
 
121
 
 
122
void config_read()
 
123
{
 
124
    char variable_bitrate_display[10];
 
125
    char priority[10];
 
126
    char memmap_file[10];
 
127
    char local_buffer_size[10];
 
128
    char stream_buffer_size[10];
 
129
 
 
130
    strcpy(variable_bitrate_display, "1");
 
131
    strcpy(priority, "5");
 
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(memmap_file);
 
139
    RS(local_buffer_size);
 
140
    RS(stream_buffer_size);
 
141
 
 
142
    m_priority = atoi(priority);
 
143
    m_variable_bitrate_display = atoi(variable_bitrate_display);
 
144
    m_memmap_file = atoi(memmap_file);
 
145
    m_local_buffer_size = atoi(local_buffer_size);
 
146
    m_stream_buffer_size = atoi(stream_buffer_size);
 
147
}
 
148
 
 
149
void config_write()
 
150
{
 
151
    char variable_bitrate_display[10];
 
152
    char priority[10];
 
153
    char memmap_file[10];
 
154
    char local_buffer_size[10];
 
155
    char stream_buffer_size[10];
 
156
 
 
157
    itoa(m_priority, priority, 10);
 
158
    itoa(m_variable_bitrate_display, variable_bitrate_display, 10);
 
159
    itoa(m_memmap_file, memmap_file, 10);
 
160
    itoa(m_local_buffer_size, local_buffer_size, 10);
 
161
    itoa(m_stream_buffer_size, stream_buffer_size, 10);
 
162
 
 
163
    WS(variable_bitrate_display);
 
164
    WS(priority);
 
165
    WS(memmap_file);
 
166
    WS(local_buffer_size);
 
167
    WS(stream_buffer_size);
 
168
}
 
169
 
 
170
//-----------------------------------------------------------------------------
 
171
 
 
172
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID pRes)
 
173
{
 
174
        if (fdwReason == DLL_PROCESS_ATTACH)
 
175
                hInstance = hInst;
 
176
        return TRUE;
 
177
}
 
178
 
 
179
//-----------------------------------------------------------------------------
 
180
//old entrypoint api
 
181
PLUGIN_API BOOL QInputModule(QCDModInitIn *ModInit, QCDModInfo *ModInfo)
 
182
{
 
183
        ModInit->version                                        = PLUGIN_API_VERSION;
 
184
        ModInit->toModule.ShutDown                      = ShutDown;
 
185
        ModInit->toModule.GetTrackExtents       = GetTrackExtents;
 
186
        ModInit->toModule.GetMediaSupported = GetMediaSupported;
 
187
        ModInit->toModule.GetCurrentPosition= GetCurrentPosition;
 
188
        ModInit->toModule.Play                          = Play;
 
189
        ModInit->toModule.Pause                         = Pause;
 
190
        ModInit->toModule.Stop                          = Stop;
 
191
        ModInit->toModule.SetVolume                     = SetVolume;
 
192
        ModInit->toModule.About                         = About;
 
193
        ModInit->toModule.Configure                     = Configure;
 
194
        QCDCallbacks = ModInit;
 
195
 
 
196
        ModInfo->moduleString = "FAAD Plugin v1.0b";
 
197
        /* read config */
 
198
        QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
 
199
 
 
200
        config_read();
 
201
        ModInfo->moduleExtensions = "AAC";
 
202
 
 
203
        hwndPlayer = (HWND)ModInit->Service(opGetParentWnd, 0, 0, 0);
 
204
        lastfn[0] = 0;
 
205
        play_thread_handle = INVALID_HANDLE_VALUE;
 
206
 
 
207
        oldAPIs = 1;
 
208
 
 
209
        return TRUE;
 
210
}
 
211
 
 
212
//-----------------------------------------------------------------------------
 
213
 
 
214
PLUGIN_API QCDModInitIn* INPUTDLL_ENTRY_POINT()
 
215
{
 
216
        sQCDCallbacks.version                                           = PLUGIN_API_VERSION;
 
217
        sQCDCallbacks.toModule.Initialize                       = Initialize;
 
218
        sQCDCallbacks.toModule.ShutDown                         = ShutDown;
 
219
        sQCDCallbacks.toModule.GetTrackExtents          = GetTrackExtents;
 
220
        sQCDCallbacks.toModule.GetMediaSupported        = GetMediaSupported;
 
221
        sQCDCallbacks.toModule.GetCurrentPosition       = GetCurrentPosition;
 
222
        sQCDCallbacks.toModule.Play                                     = Play;
 
223
        sQCDCallbacks.toModule.Pause                            = Pause;
 
224
        sQCDCallbacks.toModule.Stop                                     = Stop;
 
225
        sQCDCallbacks.toModule.SetVolume                        = SetVolume;
 
226
        sQCDCallbacks.toModule.About                            = About;
 
227
        sQCDCallbacks.toModule.Configure                        = Configure;
 
228
 
 
229
        QCDCallbacks = &sQCDCallbacks;
 
230
        return &sQCDCallbacks;
 
231
}
 
232
 
 
233
//----------------------------------------------------------------------------
 
234
 
 
235
BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
 
236
{
 
237
        char tmp[10];
 
238
 
 
239
    switch (message)
 
240
        {
 
241
    case WM_INITDIALOG:
 
242
        /* Set priority slider range and previous position */
 
243
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(1, 5)); 
 
244
                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, m_priority);
 
245
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
 
246
                
 
247
                /* Put a limit to the amount of characters allowed in the buffer boxes */
 
248
                SendMessage(GetDlgItem(hwndDlg, LOCAL_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
 
249
                SendMessage(GetDlgItem(hwndDlg, STREAM_BUFFER_TXT), EM_LIMITTEXT, 4, 0);
 
250
 
 
251
            if(m_variable_bitrate_display)
 
252
                        SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0);
 
253
            if(m_memmap_file)
 
254
                        SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_CHECKED, 0);
 
255
 
 
256
                itoa(m_local_buffer_size, tmp, 10);
 
257
                SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp);
 
258
 
 
259
                itoa(m_stream_buffer_size, tmp, 10);
 
260
                SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp);
 
261
 
 
262
                return TRUE;
 
263
 
 
264
        case WM_HSCROLL:
 
265
 
 
266
                /* Thread priority slider moved */
 
267
                if(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER) == (HWND) lParam)
 
268
                {
 
269
                        int tmp;
 
270
                        tmp = SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_GETPOS, 0, 0);
 
271
 
 
272
                        if(tmp > 0)
 
273
                        {
 
274
                                m_priority = tmp;
 
275
 
 
276
                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]);
 
277
 
 
278
                                if(play_thread_handle)
 
279
                                        SetThreadPriority(play_thread_handle, priority_table[m_priority]);
 
280
                        }
 
281
                }
 
282
 
 
283
                return TRUE;
 
284
 
 
285
    case WM_COMMAND:
 
286
 
 
287
                if(HIWORD(wParam) == BN_CLICKED)
 
288
                {
 
289
                        if(GetDlgItem(hwndDlg, VARBITRATE_CHK) == (HWND) lParam)
 
290
                        {
 
291
                                /* Variable Bitrate checkbox hit */
 
292
                                m_variable_bitrate_display = SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_GETCHECK, 0, 0); 
 
293
                        }
 
294
                        if(GetDlgItem(hwndDlg, IDC_MEMMAP) == (HWND) lParam)
 
295
                        {
 
296
                                /* Variable Bitrate checkbox hit */
 
297
                                m_memmap_file = SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_GETCHECK, 0, 0); 
 
298
                        }
 
299
                }
 
300
 
 
301
        switch (LOWORD(wParam))
 
302
                {
 
303
                        case OK_BTN:
 
304
                                /* User hit OK, save buffer settings (all others are set on command) */
 
305
                                GetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp, 5);
 
306
                                m_local_buffer_size = atol(tmp);
 
307
 
 
308
                                GetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp, 5);
 
309
                                m_stream_buffer_size = atol(tmp);
 
310
 
 
311
                config_write();
 
312
 
 
313
                                EndDialog(hwndDlg, wParam);
 
314
                                return TRUE;
 
315
                        case RESET_BTN:
 
316
                                SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0);
 
317
                                m_variable_bitrate_display = 1;
 
318
                                SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_UNCHECKED, 0);
 
319
                                m_memmap_file = 0;
 
320
                                SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, 5);
 
321
                                m_priority = 5;
 
322
                                SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[5]);
 
323
                                SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, "128");
 
324
                                m_local_buffer_size = 128;
 
325
                                SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, "64");
 
326
                                m_stream_buffer_size = 64;
 
327
                                return TRUE;
 
328
                        case IDCANCEL:
 
329
                        case CANCEL_BTN:
 
330
                                /* User hit Cancel or the X, just close without saving buffer settings */
 
331
                                DestroyWindow(hwndDlg);
 
332
                                return TRUE;
 
333
        }
 
334
    }
 
335
    return FALSE;
 
336
}
 
337
 
 
338
 
 
339
void Configure(int flags)
 
340
{
 
341
        if(!IsWindow(hwndConfig))
 
342
                hwndConfig = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG), hwndPlayer, config_dialog_proc);
 
343
        ShowWindow(hwndConfig, SW_NORMAL);
 
344
}
 
345
 
 
346
//-----------------------------------------------------------------------------
 
347
// proc of "About Dialog"
 
348
INT_PTR CALLBACK about_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
349
{
 
350
        static RECT rcLOGO, rcMail1, rcMail2/*, rcMail3*/;
 
351
        POINT ptMouse;
 
352
        static char szPluginVer[] = "QCD FAAD Input Plug-in v1.0b\nCompiled on " __TIME__ ", " __DATE__;
 
353
        static char szFLACVer[] = "Using: FAAD2 v "FAAD2_VERSION" by";
 
354
 
 
355
        switch (uMsg)
 
356
        {
 
357
        case WM_INITDIALOG:
 
358
        case WM_MOVE:
 
359
                GetWindowRect(GetDlgItem(hwndDlg, IDC_LOGO), &rcLOGO);
 
360
                GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL1), &rcMail1);
 
361
                GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail2);
 
362
//              GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail3);
 
363
 
 
364
                SetDlgItemText(hwndDlg, IDC_PLUGINVER, szPluginVer);
 
365
                SetDlgItemText(hwndDlg, IDC_FAADVER, szFLACVer);
 
366
                
 
367
                return TRUE;
 
368
        case WM_MOUSEMOVE:
 
369
                ptMouse.x = LOWORD(lParam);
 
370
                ptMouse.y = HIWORD(lParam);
 
371
                ClientToScreen(hwndDlg, &ptMouse);
 
372
                if( (ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
 
373
                        ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom) 
 
374
                        ||
 
375
                        (ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
 
376
                        ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom) 
 
377
                        ||
 
378
                        (ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
 
379
                        ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom) 
 
380
/*                      ||
 
381
                        (ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
 
382
                        ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)*/ )
 
383
                        SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(32649)));
 
384
                else
 
385
                        SetCursor(LoadCursor(NULL, IDC_ARROW));
 
386
 
 
387
                return TRUE;
 
388
        case WM_LBUTTONDOWN:
 
389
                ptMouse.x = LOWORD(lParam);
 
390
                ptMouse.y = HIWORD(lParam);
 
391
                ClientToScreen(hwndDlg, &ptMouse);
 
392
                if(ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
 
393
                        ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom)
 
394
                        ShellExecute(0, NULL, "http://www.audiocoding.com", NULL,NULL, SW_NORMAL);
 
395
                else if(ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
 
396
                        ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom)
 
397
                        ShellExecute(0, NULL, "mailto:shaohao@elong.com", NULL,NULL, SW_NORMAL);
 
398
                else if(ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
 
399
                        ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom)
 
400
                        ShellExecute(0, NULL, "mailto:menno@audiocoding.com", NULL,NULL, SW_NORMAL);
 
401
/*              else if(ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
 
402
                        ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)
 
403
                        ShellExecute(0, NULL, "I don't know", NULL,NULL, SW_NORMAL);
 
404
*/
 
405
                return TRUE;
 
406
        case WM_COMMAND:
 
407
                switch(LOWORD(wParam))
 
408
                {
 
409
                case IDOK:
 
410
                default:
 
411
                        DestroyWindow(hwndDlg);
 
412
                        return TRUE;
 
413
                }
 
414
        }
 
415
        return FALSE;
 
416
}
 
417
 
 
418
void About(int flags)
 
419
{
 
420
        if(!IsWindow(hwndAbout))
 
421
                hwndAbout = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwndPlayer, about_dialog_proc); 
 
422
        ShowWindow(hwndAbout, SW_SHOW);
 
423
}
 
424
 
 
425
//-----------------------------------------------------------------------------
 
426
 
 
427
BOOL Initialize(QCDModInfo *ModInfo, int flags)
 
428
{
 
429
        hwndPlayer = (HWND)QCDCallbacks->Service(opGetParentWnd, 0, 0, 0);
 
430
 
 
431
        lastfn[0] = 0;
 
432
        seek_needed = -1;
 
433
        paused = 0;
 
434
        play_thread_handle = INVALID_HANDLE_VALUE;
 
435
 
 
436
        /* read config */
 
437
        QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
 
438
    config_read();
 
439
 
 
440
        ModInfo->moduleString = "FAAD Plugin v1.0b";
 
441
        ModInfo->moduleExtensions = "AAC";
 
442
 
 
443
    /* Initialize winsock, necessary for streaming */
 
444
    WinsockInit();
 
445
 
 
446
        // insert menu item into plugin menu
 
447
//      QCDCallbacks->Service(opSetPluginMenuItem, hInstance, IDD_CONFIG, (long)"FAAD Plug-in");
 
448
 
 
449
        return TRUE;
 
450
}
 
451
 
 
452
//----------------------------------------------------------------------------
 
453
 
 
454
void ShutDown(int flags)
 
455
{
 
456
        Stop(lastfn, STOPFLAG_FORCESTOP);
 
457
 
 
458
    if(buffer)
 
459
                LocalFree(buffer);
 
460
 
 
461
    /* Deallocate winsock */
 
462
    WinsockDeInit();
 
463
 
 
464
        // delete the inserted plugin menu
 
465
//      QCDCallbacks->Service(opSetPluginMenuItem, hInstance, 0, 0);
 
466
}
 
467
 
 
468
//-----------------------------------------------------------------------------
 
469
 
 
470
BOOL GetMediaSupported(LPCSTR medianame, MediaInfo *mediaInfo)
 
471
{
 
472
        FILE_STREAM *in;
 
473
        faadAACInfo tmp;
 
474
        char *ch = strrchr(medianame, '.');
 
475
 
 
476
        if (!medianame || !*medianame)
 
477
                return FALSE;
 
478
 
 
479
        if(!ch)
 
480
                return (lstrlen(medianame) > 2); // no extension defaults to me (if not drive letter)
 
481
 
 
482
   /* Finally fixed */
 
483
    if(StringComp(ch, ".aac", 4) == 0)
 
484
    {
 
485
                in = open_filestream((char *)medianame);
 
486
                
 
487
                if(in != NULL && mediaInfo)
 
488
                {
 
489
                        if(in->http)
 
490
                        {
 
491
                                /* No seeking in http streams */
 
492
                                mediaInfo->mediaType = DIGITAL_STREAM_MEDIA;
 
493
                                mediaInfo->op_canSeek = FALSE;
 
494
                        }
 
495
                        else
 
496
                        {
 
497
                                mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
 
498
                            get_AAC_format((char *)medianame, &tmp, NULL, NULL, 1);
 
499
                                if(tmp.headertype == 2) /* ADTS header - seekable */
 
500
                                        mediaInfo->op_canSeek = TRUE;
 
501
                                else
 
502
                                        mediaInfo->op_canSeek = FALSE; /* ADIF or Headerless - not seekable */
 
503
                        }
 
504
                        
 
505
                        close_filestream(in);
 
506
                        return TRUE;
 
507
                }
 
508
                else
 
509
                {
 
510
                        close_filestream(in);
 
511
                        return FALSE;
 
512
                }
 
513
        }
 
514
        else
 
515
                return FALSE;           
 
516
}
 
517
 
 
518
unsigned long samplerate, channels;
 
519
 
 
520
int play_memmap(char *fn)
 
521
{
 
522
    int tagsize = 0;
 
523
 
 
524
    infile = open_filestream(fn);
 
525
    
 
526
        if (infile == NULL)
 
527
        return 1;
 
528
 
 
529
    fileread = filelength_filestream(infile);
 
530
 
 
531
    memmap_buffer = (char*)LocalAlloc(LPTR, fileread);
 
532
    read_buffer_filestream(infile, memmap_buffer, fileread);
 
533
 
 
534
    /* skip id3v2 tag */
 
535
    memmap_index = id3v2_tag(memmap_buffer);
 
536
 
 
537
    hDecoder = faacDecOpen();
 
538
 
 
539
        /* Copy the configuration dialog setting and use it as the default */
 
540
        /* initialize the decoder, and get samplerate and channel info */
 
541
 
 
542
    if( (buffercount = faacDecInit(hDecoder, memmap_buffer + memmap_index,
 
543
        fileread - memmap_index - 1, &samplerate, &channels)) < 0 )
 
544
    {
 
545
                show_error("Error opening input file");
 
546
                return 1;
 
547
    }
 
548
 
 
549
    memmap_index += buffercount;
 
550
 
 
551
    PlayThread_memmap();
 
552
 
 
553
    return 0;
 
554
}
 
555
 
 
556
int play_file(char *fn)
 
557
{
 
558
    int k;
 
559
    int tagsize;
 
560
 
 
561
    ZeroMemory(buffer, 768*2);
 
562
 
 
563
     infile = open_filestream(fn);
 
564
    
 
565
        if (infile == NULL)
 
566
        return 1;
 
567
 
 
568
        fileread = filelength_filestream(infile);
 
569
 
 
570
    buffercount = bytecount = 0;
 
571
    read_buffer_filestream(infile, buffer, 768*2);
 
572
 
 
573
    tagsize = id3v2_tag(buffer);
 
574
 
 
575
        /* If we find a tag, run right over it */
 
576
    if(tagsize)
 
577
        {
 
578
        if(infile->http)
 
579
        {
 
580
            int i;
 
581
            /* Crude way of doing this, but I believe its fast enough to not make a big difference */
 
582
            close_filestream(infile);
 
583
            infile = open_filestream(fn);
 
584
 
 
585
            for(i=0; i < tagsize; i++)
 
586
                read_byte_filestream(infile);
 
587
        }
 
588
        else
 
589
            seek_filestream(infile, tagsize, FILE_BEGIN);
 
590
 
 
591
        bytecount = tagsize;
 
592
        buffercount = 0;
 
593
        read_buffer_filestream(infile, buffer, 768*2);
 
594
    }
 
595
 
 
596
    hDecoder = faacDecOpen();
 
597
 
 
598
        /* Copy the configuration dialog setting and use it as the default */
 
599
        /* initialize the decoder, and get samplerate and channel info */
 
600
 
 
601
    if((buffercount = faacDecInit(hDecoder, buffer, 768*2, &samplerate, &channels)) < 0)
 
602
    {
 
603
                show_error("Error opening input file");
 
604
                return 1;
 
605
    }
 
606
 
 
607
    if(buffercount > 0)
 
608
        {
 
609
                bytecount += buffercount;
 
610
 
 
611
                for (k = 0; k < (768*2 - buffercount); k++)
 
612
                        buffer[k] = buffer[k + buffercount];
 
613
 
 
614
                read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
 
615
                buffercount = 0;
 
616
        }
 
617
 
 
618
    PlayThread_file();
 
619
 
 
620
    return 0;
 
621
}
 
622
 
 
623
 
 
624
//-----------------------------------------------------------------------------
 
625
 
 
626
BOOL Play(LPCSTR medianame, int playfrom, int playto, int flags)
 
627
{
 
628
        if(stricmp(lastfn, medianame) != 0)
 
629
        {
 
630
                sQCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
 
631
                Stop(lastfn, STOPFLAG_PLAYDONE);
 
632
        }
 
633
 
 
634
        if(paused)
 
635
        {
 
636
                // Update the player controls to reflect the new unpaused state
 
637
                sQCDCallbacks.toPlayer.OutputPause(0);
 
638
 
 
639
                Pause(medianame, PAUSE_DISABLED);
 
640
 
 
641
                if (playfrom >= 0)
 
642
                        seek_needed = playfrom;
 
643
        }
 
644
        else if(play_thread_handle != INVALID_HANDLE_VALUE)
 
645
        {
 
646
                seek_needed = playfrom;
 
647
                return TRUE;
 
648
        }
 
649
        else
 
650
        {
 
651
                int thread_id;
 
652
 
 
653
                // alloc the input buffer
 
654
                buffer = (unsigned char*)LocalAlloc(LPTR, 768*2);
 
655
 
 
656
                current_file_mode = m_memmap_file;
 
657
                
 
658
                if(current_file_mode)
 
659
                {
 
660
                        if(play_memmap((char *)medianame))
 
661
                                return FALSE;
 
662
                }
 
663
                else
 
664
                {
 
665
                        if(play_file((char *)medianame))
 
666
                                return FALSE;
 
667
                }
 
668
                
 
669
                if(seek_table)
 
670
                {
 
671
                        free(seek_table);
 
672
                        seek_table = NULL;
 
673
                        seek_table_length = 0;
 
674
                }
 
675
                
 
676
                get_AAC_format((char *)medianame, &file_info, &seek_table, &seek_table_length, 0);
 
677
                
 
678
                seek_needed = playfrom > 0 ? playfrom : -1;
 
679
                killPlayThread = 0;
 
680
                strcpy(lastfn,medianame);
 
681
 
 
682
                /*
 
683
                To RageAmp: This is really needed, because aacinfo isn't very accurate on ADIF files yet.
 
684
                Can be fixed though :-)
 
685
                */
 
686
                file_info.sampling_rate = samplerate;
 
687
                file_info.channels = frameInfo.channels;
 
688
 
 
689
                play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id);
 
690
                if(!play_thread_handle)
 
691
                        return FALSE;
 
692
                
 
693
                // Note: This line seriously slows down start up time
 
694
                if(m_priority != 3) // if the priority in config window is set to normal, there is nothing to reset!
 
695
                        SetThreadPriority(play_thread_handle, priority_table[m_priority]);
 
696
                
 
697
    }
 
698
 
 
699
        return TRUE;
 
700
}
 
701
 
 
702
//-----------------------------------------------------------------------------
 
703
 
 
704
BOOL Pause(LPCSTR medianame, int flags)
 
705
{
 
706
        if(QCDCallbacks->toPlayer.OutputPause(flags))
 
707
        {
 
708
                // send back pause/unpause notification
 
709
                QCDCallbacks->toPlayer.PlayPaused(medianame, flags);
 
710
                paused = flags;
 
711
                return TRUE;
 
712
        }
 
713
        return FALSE;
 
714
}
 
715
 
 
716
//-----------------------------------------------------------------------------
 
717
 
 
718
BOOL Stop(LPCSTR medianame, int flags)
 
719
{
 
720
        if(medianame && *medianame && stricmp(lastfn, medianame) == 0)
 
721
        {
 
722
                sQCDCallbacks.toPlayer.OutputStop(flags);
 
723
                
 
724
                killPlayThread = 1;
 
725
                if(play_thread_handle != INVALID_HANDLE_VALUE)
 
726
                {
 
727
                        if(WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
 
728
                        {
 
729
//                              MessageBox(hwndPlayer, "FAAD thread kill timeout", "debug", 0);
 
730
                                TerminateThread(play_thread_handle,0);
 
731
                        }
 
732
                        CloseHandle(play_thread_handle);
 
733
                        play_thread_handle = INVALID_HANDLE_VALUE;
 
734
                }
 
735
 
 
736
                if (oldAPIs)
 
737
                        QCDCallbacks->toPlayer.PlayStopped(lastfn);
 
738
                
 
739
                lastfn[0] = 0;
 
740
        }
 
741
 
 
742
        return TRUE;
 
743
}
 
744
 
 
745
int aac_seek(int pos_ms, int *sktable)
 
746
{
 
747
    double offset_sec;
 
748
 
 
749
    offset_sec = pos_ms / 1000.0;
 
750
    if(!current_file_mode)
 
751
    {
 
752
        seek_filestream(infile, sktable[(int)(offset_sec+0.5)], FILE_BEGIN);
 
753
 
 
754
        bytecount = sktable[(int)(offset_sec+0.5)];
 
755
        buffercount = 0;
 
756
        read_buffer_filestream(infile, buffer, 768*2);
 
757
    }
 
758
        else
 
759
        {
 
760
        memmap_index = sktable[(int)(offset_sec+0.5)];
 
761
    }
 
762
 
 
763
    return 0;
 
764
}
 
765
 
 
766
//-----------------------------------------------------------------------------
 
767
 
 
768
void SetVolume(int levelleft, int levelright, int flags)
 
769
{
 
770
        QCDCallbacks->toPlayer.OutputSetVol(levelleft, levelright, flags);
 
771
}
 
772
 
 
773
//-----------------------------------------------------------------------------
 
774
 
 
775
BOOL GetCurrentPosition(LPCSTR medianame, long *track, long *offset)
 
776
{
 
777
        return QCDCallbacks->toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
 
778
}
 
779
 
 
780
//-----------------------------------------------------------------------------
 
781
 
 
782
BOOL GetTrackExtents(LPCSTR medianame, TrackExtents *ext, int flags)
 
783
{
 
784
    faadAACInfo tmp;
 
785
 
 
786
    if(get_AAC_format((char*)medianame, &tmp, NULL, NULL, 1))
 
787
                return FALSE;
 
788
 
 
789
        ext->track = 1;
 
790
        ext->start = 0;
 
791
        ext->end = tmp.length;
 
792
        ext->bytesize = tmp.bitrate * tmp.length;
 
793
        ext->unitpersec = 1000;
 
794
 
 
795
        return TRUE;
 
796
}
 
797
 
 
798
//--------------------------for play thread-------------------------------------
 
799
 
 
800
int last_frame;
 
801
 
 
802
DWORD WINAPI PlayThread(void *b)
 
803
{
 
804
    BOOL done = FALSE, updatePos = FALSE;
 
805
        int decode_pos_ms = 0; // current decoding position, in milliseconds
 
806
    int l;
 
807
        int decoded_frames=0;
 
808
        int br_calc_frames=0;
 
809
        int br_bytes_consumed=0;
 
810
    unsigned long bytesconsumed;
 
811
 
 
812
    last_frame = 0;
 
813
 
 
814
        if(!done)
 
815
        {
 
816
                // open outputdevice
 
817
                WAVEFORMATEX wf;
 
818
                wf.wFormatTag = WAVE_FORMAT_PCM;
 
819
                wf.cbSize = 0;
 
820
                wf.nChannels = file_info.channels;
 
821
                wf.wBitsPerSample = 16;
 
822
                wf.nSamplesPerSec = file_info.sampling_rate;
 
823
                wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
 
824
                wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
 
825
                if (!QCDCallbacks->toPlayer.OutputOpen(lastfn, &wf))
 
826
                {
 
827
                        show_error("Error: Failed openning output plugin!");
 
828
                        done = TRUE; // cannot open sound device
 
829
                }
 
830
        }
 
831
 
 
832
    while (! *((int *)b) )
 
833
    {
 
834
                /********************** SEEK ************************/
 
835
       if (!done && seek_needed >= 0)
 
836
           {
 
837
            int seconds;
 
838
 
 
839
            // Round off to a second
 
840
            seconds = seek_needed - (seek_needed%1000);
 
841
                        QCDCallbacks->toPlayer.OutputFlush(decode_pos_ms);
 
842
            aac_seek(seconds, seek_table);
 
843
            decode_pos_ms = seconds;
 
844
                        decoded_frames = 0;
 
845
                        br_calc_frames = 0;
 
846
                        br_bytes_consumed = 0;
 
847
 
 
848
                        seek_needed = -1;
 
849
                        updatePos = 1;
 
850
           }
 
851
 
 
852
                /********************* QUIT *************************/
 
853
                if (done)
 
854
                {
 
855
                        if (QCDCallbacks->toPlayer.OutputDrain(0) && !(seek_needed >= 0))
 
856
                        {
 
857
                                play_thread_handle = INVALID_HANDLE_VALUE;
 
858
                                QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE);
 
859
                                QCDCallbacks->toPlayer.PlayDone(lastfn);
 
860
                        }
 
861
                        else if (seek_needed >= 0)
 
862
                        {
 
863
                                done = FALSE;
 
864
                                continue;
 
865
                        }
 
866
                        break;
 
867
                }
 
868
 
 
869
        /******************* DECODE TO BUFFER ****************/
 
870
                else
 
871
        {
 
872
                        if (current_file_mode)
 
873
                                bytesconsumed = PlayThread_memmap();
 
874
                        else
 
875
                                bytesconsumed = PlayThread_file();
 
876
 
 
877
                        if(last_frame)
 
878
                                done = TRUE;
 
879
                        else
 
880
                        {
 
881
 
 
882
                                decoded_frames++;
 
883
                                br_calc_frames++;
 
884
                                br_bytes_consumed += bytesconsumed;
 
885
 
 
886
                                /* Update the variable bitrate about every second */
 
887
                                if(m_variable_bitrate_display && br_calc_frames == 43)
 
888
                                {
 
889
                                        AudioInfo vai;
 
890
                                        vai.struct_size = sizeof(AudioInfo);
 
891
                                        vai.frequency = file_info.sampling_rate;
 
892
                                        vai.bitrate = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07));
 
893
                                        vai.mode = (channels == 2) ? 0 : 3;
 
894
                                        vai.layer = 0;
 
895
                                        vai.level = file_info.version;
 
896
                                        QCDCallbacks->Service(opSetAudioInfo, &vai, sizeof(AudioInfo), 0);
 
897
 
 
898
                                        br_calc_frames = 0;
 
899
                                }
 
900
 
 
901
                if (!killPlayThread && (frameInfo.samples > 0))
 
902
                {
 
903
                    //update the time display
 
904
                                        if (updatePos)
 
905
                                        {
 
906
                                                QCDCallbacks->toPlayer.PositionUpdate(decode_pos_ms);
 
907
                                                updatePos = 0;
 
908
                                        }
 
909
                                        
 
910
                                        {
 
911
                                                WriteDataStruct wd;
 
912
 
 
913
                                                l = frameInfo.samples * sizeof(short);
 
914
 
 
915
                                                decode_pos_ms += (1024*1000)/file_info.sampling_rate;
 
916
                                                
 
917
                                                wd.bytelen = l;
 
918
                                                wd.data = sample_buffer;
 
919
                                                wd.markerend = 0;
 
920
                                                wd.markerstart = decode_pos_ms;
 
921
                                                wd.bps = 16;
 
922
                                                wd.nch = frameInfo.channels;
 
923
                                                wd.numsamples =l/file_info.channels/(16/8);
 
924
                                                wd.srate = file_info.sampling_rate;
 
925
                                                
 
926
                                                if (!QCDCallbacks->toPlayer.OutputWrite(&wd))
 
927
                                                        done = TRUE;
 
928
                                        }
 
929
                                }
 
930
                        }
 
931
                }
 
932
        Sleep(10);
 
933
    }
 
934
 
 
935
        // close up
 
936
        play_thread_handle = INVALID_HANDLE_VALUE;
 
937
 
 
938
        faacDecClose(hDecoder);
 
939
        hDecoder = INVALID_HANDLE_VALUE;
 
940
        close_filestream(infile);
 
941
        infile = NULL;
 
942
 
 
943
        if(seek_table)
 
944
        {
 
945
                free(seek_table);
 
946
                seek_table = NULL;
 
947
                seek_table_length = 0;
 
948
        }
 
949
 
 
950
        if(buffer)
 
951
        {
 
952
                LocalFree(buffer);
 
953
                buffer = NULL;
 
954
        }
 
955
        if(memmap_buffer)
 
956
        {
 
957
                LocalFree(memmap_buffer);
 
958
                memmap_buffer = NULL;
 
959
        }
 
960
 
 
961
    return 0;
 
962
}
 
963
 
 
964
// thread play funcs
 
965
int PlayThread_memmap()
 
966
{
 
967
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo,
 
968
        memmap_buffer + memmap_index, fileread - memmap_index - 1);
 
969
    if (frameInfo.error)
 
970
    {
 
971
//        show_error(faacDecGetErrorMessage(frameInfo.error));
 
972
        last_frame = 1;
 
973
    }
 
974
 
 
975
    memmap_index += frameInfo.bytesconsumed;
 
976
    if (memmap_index >= fileread)
 
977
        last_frame = 1;
 
978
 
 
979
    return frameInfo.bytesconsumed;
 
980
}
 
981
 
 
982
int PlayThread_file()
 
983
{
 
984
    int k;
 
985
 
 
986
    if (buffercount > 0)
 
987
        {
 
988
        for (k = 0; k < (768*2 - buffercount); k++)
 
989
            buffer[k] = buffer[k + buffercount];
 
990
 
 
991
        read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
 
992
        buffercount = 0;
 
993
    }
 
994
 
 
995
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, buffer, 768*2);
 
996
    if (frameInfo.error)
 
997
    {
 
998
//        show_error(faacDecGetErrorMessage(frameInfo.error));
 
999
        last_frame = 1;
 
1000
    }
 
1001
 
 
1002
    buffercount += frameInfo.bytesconsumed;
 
1003
 
 
1004
    bytecount += frameInfo.bytesconsumed;
 
1005
    if (bytecount >= fileread)
 
1006
        last_frame = 1;
 
1007
 
 
1008
    return frameInfo.bytesconsumed;
 
1009
}
 
1010
 
 
1011
// tag
 
1012
int id3v2_tag(unsigned char *buffer)
 
1013
{
 
1014
    if (StringComp(buffer, "ID3", 3) == 0)
 
1015
        {
 
1016
        unsigned long tagsize;
 
1017
 
 
1018
        /* high bit is not used */
 
1019
        tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
 
1020
            (buffer[8] <<  7) | (buffer[9] <<  0);
 
1021
 
 
1022
        tagsize += 10;
 
1023
 
 
1024
        return tagsize;
 
1025
    }
 
1026
        else
 
1027
        {
 
1028
        return 0;
 
1029
    }
1030
1030
}
 
 
b'\\ No newline at end of file'