xref: /haiku/src/add-ons/media/plugins/ape_reader/MAClib/MACLib.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
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 
18 IAPEDecompress * 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 
47 IAPEDecompress * __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 
96 IAPEDecompress * __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 
106 IAPEDecompress * __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 
114 IAPECompress * __stdcall CreateIAPECompress(int * pErrorCode)
115 {
116     if (pErrorCode)
117         *pErrorCode = ERROR_SUCCESS;
118 
119     return new CAPECompress();
120 }
121 
122 int __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 
136 int __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 }