Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Common / CreateCoder.cpp
1 // CreateCoder.cpp
2
3 #include "StdAfx.h"
4
5 #include "CreateCoder.h"
6
7 #include "../../Windows/PropVariant.h"
8 #include "../../Windows/Defs.h"
9 #include "FilterCoder.h"
10 #include "RegisterCodec.h"
11
12 static const unsigned int kNumCodecsMax = 64;
13 unsigned int g_NumCodecs = 0;
14 const CCodecInfo *g_Codecs[kNumCodecsMax]; 
15 void RegisterCodec(const CCodecInfo *codecInfo) 
16
17   if (g_NumCodecs < kNumCodecsMax)
18     g_Codecs[g_NumCodecs++] = codecInfo; 
19 }
20
21 #ifdef EXTERNAL_CODECS
22 static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
23 {
24   NWindows::NCOM::CPropVariant prop;
25   RINOK(codecsInfo->GetProperty(index, propID, &prop));
26   if (prop.vt == VT_EMPTY)
27     res = 1;
28   else if (prop.vt == VT_UI4)
29     res = prop.ulVal;
30   else
31     return E_INVALIDARG;
32   return S_OK;
33 }
34
35 static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
36 {
37   NWindows::NCOM::CPropVariant prop;
38   RINOK(codecsInfo->GetProperty(index, propID, &prop));
39   if (prop.vt == VT_EMPTY)
40     res = true;
41   else if (prop.vt == VT_BOOL)
42     res = VARIANT_BOOLToBool(prop.boolVal);
43   else
44     return E_INVALIDARG;
45   return S_OK;
46 }
47
48 HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)
49 {
50   UInt32 num;
51   RINOK(codecsInfo->GetNumberOfMethods(&num));
52   for (UInt32 i = 0; i < num; i++)
53   {
54     CCodecInfoEx info;
55     NWindows::NCOM::CPropVariant prop;
56     RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));
57     // if (prop.vt != VT_BSTR)
58     // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);
59     // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);
60     if (prop.vt != VT_UI8)
61     {
62       continue; // old Interface 
63       // return E_INVALIDARG;
64     }
65     info.Id = prop.uhVal.QuadPart;
66     prop.Clear();
67     
68     RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));
69     if (prop.vt == VT_BSTR)
70       info.Name = prop.bstrVal;
71     else if (prop.vt != VT_EMPTY)
72       return E_INVALIDARG;;
73     
74     RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));
75     RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));
76     RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
77     RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
78     
79     externalCodecs.Add(info);
80   }
81   return S_OK;
82 }
83
84 #endif
85
86 bool FindMethod(
87   #ifdef EXTERNAL_CODECS
88   ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
89   #endif
90   const UString &name,
91   CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)
92 {
93   UInt32 i;
94   for (i = 0; i < g_NumCodecs; i++)
95   {
96     const CCodecInfo &codec = *g_Codecs[i]; 
97     if (name.CompareNoCase(codec.Name) == 0)
98     {
99       methodId = codec.Id;
100       numInStreams = codec.NumInStreams;
101       numOutStreams = 1;
102       return true;
103     }
104   }
105   #ifdef EXTERNAL_CODECS
106   if (externalCodecs)
107     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
108     {
109       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
110       if (codec.Name.CompareNoCase(name) == 0)
111       {
112         methodId = codec.Id;
113         numInStreams = codec.NumInStreams;
114         numOutStreams = codec.NumOutStreams;
115         return true;
116       }
117     }
118   #endif
119   return false;
120 }
121
122 bool FindMethod(
123   #ifdef EXTERNAL_CODECS
124   ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
125   #endif
126   CMethodId methodId, UString &name)
127 {
128   UInt32 i;
129   for (i = 0; i < g_NumCodecs; i++)
130   {
131     const CCodecInfo &codec = *g_Codecs[i]; 
132     if (methodId == codec.Id)
133     {
134       name = codec.Name;
135       return true;
136     }
137   }
138   #ifdef EXTERNAL_CODECS
139   if (externalCodecs)
140     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
141     {
142       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
143       if (methodId == codec.Id)
144       {
145         name = codec.Name;
146         return true;
147       }
148     }
149   #endif
150   return false;
151 }
152
153 HRESULT CreateCoder(
154   DECL_EXTERNAL_CODECS_LOC_VARS
155   CMethodId methodId,
156   CMyComPtr<ICompressFilter> &filter,
157   CMyComPtr<ICompressCoder> &coder,
158   CMyComPtr<ICompressCoder2> &coder2,
159   bool encode, bool onlyCoder)
160 {
161   bool created = false;
162   UInt32 i;
163   for (i = 0; i < g_NumCodecs; i++)
164   {
165     const CCodecInfo &codec = *g_Codecs[i]; 
166     if (codec.Id == methodId)
167     {
168       if (encode)
169       {
170         if (codec.CreateEncoder)
171         {
172           void *p = codec.CreateEncoder();
173           if (codec.IsFilter) filter = (ICompressFilter *)p;
174           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
175           else coder2 = (ICompressCoder2 *)p;
176           created = (p != 0);
177           break;
178         }
179       }
180       else
181         if (codec.CreateDecoder)
182         {
183           void *p = codec.CreateDecoder();
184           if (codec.IsFilter) filter = (ICompressFilter *)p;
185           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
186           else coder2 = (ICompressCoder2 *)p;
187           created = (p != 0);
188           break;
189         }
190     }
191   }
192
193   #ifdef EXTERNAL_CODECS
194   if (!created && externalCodecs)
195     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
196     {
197       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
198       if (codec.Id == methodId)
199       {
200         if (encode)
201         {
202           if (codec.EncoderIsAssigned)
203           {
204             if (codec.IsSimpleCodec())
205             {
206               HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);
207               if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
208                 return result;
209               if (!coder)
210               {
211                 RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));
212               }
213             }
214             else
215             {
216               RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
217             }
218             break;
219           }
220         }
221         else
222           if (codec.DecoderIsAssigned)
223           {
224             if (codec.IsSimpleCodec())
225             {
226               HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);
227               if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
228                 return result;
229               if (!coder)
230               {
231                 RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));
232               }
233             }
234             else
235             {
236               RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));
237             }
238             break;
239           }
240       }
241     }
242   #endif
243
244   if (onlyCoder && filter)
245   {
246     CFilterCoder *coderSpec = new CFilterCoder;
247     coder = coderSpec;
248     coderSpec->Filter = filter;
249   }
250   return S_OK;
251 }
252
253 HRESULT CreateCoder(
254   DECL_EXTERNAL_CODECS_LOC_VARS
255   CMethodId methodId,
256   CMyComPtr<ICompressCoder> &coder, 
257   CMyComPtr<ICompressCoder2> &coder2,
258   bool encode)
259 {
260   CMyComPtr<ICompressFilter> filter;
261   return CreateCoder(
262     EXTERNAL_CODECS_LOC_VARS
263     methodId,
264     filter, coder, coder2, encode, true);
265 }
266
267 HRESULT CreateCoder(
268   DECL_EXTERNAL_CODECS_LOC_VARS
269   CMethodId methodId,
270   CMyComPtr<ICompressCoder> &coder, bool encode)
271 {
272   CMyComPtr<ICompressFilter> filter;
273   CMyComPtr<ICompressCoder2> coder2;
274   return CreateCoder(
275     EXTERNAL_CODECS_LOC_VARS
276     methodId,
277     coder, coder2, encode);
278 }
279
280 HRESULT CreateFilter(
281   DECL_EXTERNAL_CODECS_LOC_VARS
282   CMethodId methodId,
283   CMyComPtr<ICompressFilter> &filter,
284   bool encode)
285 {
286   CMyComPtr<ICompressCoder> coder;
287   CMyComPtr<ICompressCoder2> coder2;
288   return CreateCoder(
289     EXTERNAL_CODECS_LOC_VARS
290     methodId,
291     filter, coder, coder2, encode, false);
292 }