1#include "All.h"
2#include "MACLib.h"
3
4//#include "APECompress.h"
5//#include "APECompressCreate.h"
6//#include "APECompressCore.h"
7#include "APECompress.h"
8#include "APEDecompress.h"
9#include "APEInfo.h"
10#include "APELink.h"
11
12#undef	BACKWARDS_COMPATIBILITY
13
14#ifdef BACKWARDS_COMPATIBILITY
15    #include "Old/APEDecompressOld.h"
16#endif
17
18IAPEDecompress * CreateIAPEDecompressCore(CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock, int * pErrorCode)
19{
20    IAPEDecompress * pAPEDecompress = NULL;
21    if (pAPEInfo != NULL && *pErrorCode == ERROR_SUCCESS)
22    {
23        try
24        {
25            if (pAPEInfo->GetInfo(APE_INFO_FILE_VERSION) >= 3930)
26                pAPEDecompress = new CAPEDecompress(pErrorCode, pAPEInfo, nStartBlock, nFinishBlock);
27#ifdef BACKWARDS_COMPATIBILITY
28            else
29                pAPEDecompress = new CAPEDecompressOld(pErrorCode, pAPEInfo, nStartBlock, nFinishBlock);
30#endif
31
32            if (pAPEDecompress == NULL || *pErrorCode != ERROR_SUCCESS)
33            {
34                SAFE_DELETE(pAPEDecompress)
35            }
36        }
37        catch(...)
38        {
39            SAFE_DELETE(pAPEDecompress)
40            *pErrorCode = ERROR_UNDEFINED;
41        }
42    }
43
44    return pAPEDecompress;
45}
46
47IAPEDecompress * __stdcall CreateIAPEDecompress(const str_utf16 * pFilename, int * pErrorCode)
48{
49    // error check the parameters
50    if ((pFilename == NULL) || (wcslen(pFilename) == 0))
51    {
52        if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
53        return NULL;
54    }
55
56    // variables
57    int nErrorCode = ERROR_UNDEFINED;
58    CAPEInfo * pAPEInfo = NULL;
59    int nStartBlock = -1; int nFinishBlock = -1;
60
61    // get the extension
62    const str_utf16 * pExtension = &pFilename[wcslen(pFilename)];
63    while ((pExtension > pFilename) && (*pExtension != '.'))
64        pExtension--;
65
66    // take the appropriate action (based on the extension)
67    if (wcsicmp(pExtension, ".apl") == 0)
68    {
69        // "link" file (.apl linked large APE file)
70        CAPELink APELink(pFilename);
71        if (APELink.GetIsLinkFile())
72        {
73            pAPEInfo = new CAPEInfo(&nErrorCode, APELink.GetImageFilename(), new CAPETag(pFilename, TRUE));
74            nStartBlock = APELink.GetStartBlock(); nFinishBlock = APELink.GetFinishBlock();
75        }
76    }
77    else /*if ((wcsicmp(pExtension, L".mac") == 0) || (wcsicmp(pExtension, L".ape") == 0))*/		// SHINTA: To play regardless of the extension.
78    {
79        // plain .ape file
80        pAPEInfo = new CAPEInfo(&nErrorCode, pFilename);
81    }
82
83    // fail if we couldn't get the file information
84    if (pAPEInfo == NULL)
85    {
86        if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
87        return NULL;
88    }
89
90    // create and return
91    IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, nStartBlock, nFinishBlock, &nErrorCode);
92    if (pErrorCode) *pErrorCode = nErrorCode;
93    return pAPEDecompress;
94}
95
96IAPEDecompress * __stdcall CreateIAPEDecompressEx(CIO * pIO, int * pErrorCode)
97{
98    int nErrorCode = ERROR_UNDEFINED;
99    CAPEInfo * pAPEInfo = new CAPEInfo(&nErrorCode, pIO);
100    IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, -1, -1, &nErrorCode);
101    if (pErrorCode) *pErrorCode = nErrorCode;
102    return pAPEDecompress;
103}
104
105
106IAPEDecompress * __stdcall CreateIAPEDecompressEx2(CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock, int * pErrorCode)
107{
108    int nErrorCode = ERROR_SUCCESS;
109    IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, nStartBlock, nFinishBlock, &nErrorCode);
110    if (pErrorCode) *pErrorCode = nErrorCode;
111    return pAPEDecompress;
112}
113
114IAPECompress * __stdcall CreateIAPECompress(int * pErrorCode)
115{
116    if (pErrorCode)
117        *pErrorCode = ERROR_SUCCESS;
118
119    return new CAPECompress();
120}
121
122int __stdcall FillWaveFormatEx(WAVEFORMATEX * pWaveFormatEx, int nSampleRate, int nBitsPerSample, int nChannels)
123{
124    pWaveFormatEx->cbSize = 0;
125    pWaveFormatEx->nSamplesPerSec = nSampleRate;
126    pWaveFormatEx->wBitsPerSample = nBitsPerSample;
127    pWaveFormatEx->nChannels = nChannels;
128    pWaveFormatEx->wFormatTag = 1;
129
130    pWaveFormatEx->nBlockAlign = (pWaveFormatEx->wBitsPerSample / 8) * pWaveFormatEx->nChannels;
131    pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nBlockAlign * pWaveFormatEx->nSamplesPerSec;
132
133    return ERROR_SUCCESS;
134}
135
136int __stdcall FillWaveHeader(WAVE_HEADER * pWAVHeader, int nAudioBytes, WAVEFORMATEX * pWaveFormatEx, int nTerminatingBytes)
137{
138    try
139    {
140        // RIFF header
141        memcpy(pWAVHeader->cRIFFHeader, "RIFF", 4);
142        pWAVHeader->nRIFFBytes = (nAudioBytes + 44) - 8 + nTerminatingBytes;
143
144        // format header
145        memcpy(pWAVHeader->cDataTypeID, "WAVE", 4);
146        memcpy(pWAVHeader->cFormatHeader, "fmt ", 4);
147
148        // the format chunk is the first 16 bytes of a waveformatex
149        pWAVHeader->nFormatBytes = 16;
150        memcpy(&pWAVHeader->nFormatTag, pWaveFormatEx, 16);
151
152        // the data header
153        memcpy(pWAVHeader->cDataHeader, "data", 4);
154        pWAVHeader->nDataBytes = nAudioBytes;
155
156        return ERROR_SUCCESS;
157    }
158    catch(...) { return ERROR_UNDEFINED; }
159}