view src/win32/7zip/7z/CPP/7zip/Common/CreateCoder.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 // CreateCoder.cpp
3 #include "StdAfx.h"
5 #include "CreateCoder.h"
7 #include "../../Windows/PropVariant.h"
8 #include "../../Windows/Defs.h"
9 #include "FilterCoder.h"
10 #include "RegisterCodec.h"
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 }
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 }
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 }
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();
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;;
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));
79 externalCodecs.Add(info);
80 }
81 return S_OK;
82 }
84 #endif
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 }
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 }
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 }
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
244 if (onlyCoder && filter)
245 {
246 CFilterCoder *coderSpec = new CFilterCoder;
247 coder = coderSpec;
248 coderSpec->Filter = filter;
249 }
250 return S_OK;
251 }
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 }
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 }
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 }