2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
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, or (at your option)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
24 #include "..\..\include\winddk\devioctl.h"
25 #include "..\..\include\winddk\ntddcdrm.h"
29 #include "..\..\..\include\moreuuids.h"
30 #include <emmintrin.h>
33 #include <d3d9types.h>
37 void DumpStreamConfig(TCHAR
* fn
, IAMStreamConfig
* pAMVSCCap
)
41 if(!f
.Open(fn
, CFile::modeCreate
|CFile::modeWrite
|CFile::typeText
))
44 int cnt
= 0, size
= 0;
45 if(FAILED(pAMVSCCap
->GetNumberOfCapabilities(&cnt
, &size
)))
49 s
.Format(_T("cnt %d, size %d\n"), cnt
, size
);
52 if(size
== sizeof(VIDEO_STREAM_CONFIG_CAPS
))
54 for(int i
= 0; i
< cnt
; i
++)
56 AM_MEDIA_TYPE
* pmt
= NULL
;
58 VIDEO_STREAM_CONFIG_CAPS caps
;
59 memset(&caps
, 0, sizeof(caps
));
62 ss
.Format(_T("%d\n"), i
); s
+= ss
;
65 if(FAILED(pAMVSCCap
->GetStreamCaps(i
, &pmt
, (BYTE
*)&caps
)))
70 ss
.Format(_T("VIDEO_STREAM_CONFIG_CAPS\n")); s
+= ss
;
71 ss
.Format(_T("\tVideoStandard 0x%08x\n"), caps
.VideoStandard
); s
+= ss
;
72 ss
.Format(_T("\tInputSize %dx%d\n"), caps
.InputSize
); s
+= ss
;
73 ss
.Format(_T("\tCroppingSize %dx%d - %dx%d\n"), caps
.MinCroppingSize
, caps
.MaxCroppingSize
); s
+= ss
;
74 ss
.Format(_T("\tCropGranularity %d, %d\n"), caps
.CropGranularityX
, caps
.CropGranularityY
); s
+= ss
;
75 ss
.Format(_T("\tCropAlign %d, %d\n"), caps
.CropAlignX
, caps
.CropAlignY
); s
+= ss
;
76 ss
.Format(_T("\tOutputSize %dx%d - %dx%d\n"), caps
.MinOutputSize
, caps
.MaxOutputSize
); s
+= ss
;
77 ss
.Format(_T("\tOutputGranularity %d, %d\n"), caps
.OutputGranularityX
, caps
.OutputGranularityY
); s
+= ss
;
78 ss
.Format(_T("\tStretchTaps %d, %d\n"), caps
.StretchTapsX
, caps
.StretchTapsY
); s
+= ss
;
79 ss
.Format(_T("\tShrinkTaps %d, %d\n"), caps
.ShrinkTapsX
, caps
.ShrinkTapsY
); s
+= ss
;
80 ss
.Format(_T("\tFrameInterval %I64d, %I64d (%.4f, %.4f)\n"),
81 caps
.MinFrameInterval
, caps
.MaxFrameInterval
,
82 (float)10000000/caps
.MinFrameInterval
, (float)10000000/caps
.MaxFrameInterval
); s
+= ss
;
83 ss
.Format(_T("\tBitsPerSecond %d - %d\n"), caps
.MinBitsPerSecond
, caps
.MaxBitsPerSecond
); s
+= ss
;
87 BITMAPINFOHEADER
* pbh
;
88 if(pmt
->formattype
== FORMAT_VideoInfo
)
90 VIDEOINFOHEADER
* vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
91 pbh
= &vih
->bmiHeader
;
94 ss
.Format(_T("FORMAT_VideoInfo\n")); s
+= ss
;
95 ss
.Format(_T("\tAvgTimePerFrame %I64d, %.4f\n"), vih
->AvgTimePerFrame
, (float)10000000/vih
->AvgTimePerFrame
); s
+= ss
;
96 ss
.Format(_T("\trcSource %d,%d,%d,%d\n"), vih
->rcSource
); s
+= ss
;
97 ss
.Format(_T("\trcTarget %d,%d,%d,%d\n"), vih
->rcTarget
); s
+= ss
;
100 else if(pmt
->formattype
== FORMAT_VideoInfo2
)
102 VIDEOINFOHEADER2
* vih
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
103 pbh
= &vih
->bmiHeader
;
106 ss
.Format(_T("FORMAT_VideoInfo2\n")); s
+= ss
;
107 ss
.Format(_T("\tAvgTimePerFrame %I64d, %.4f\n"), vih
->AvgTimePerFrame
, (float)10000000/vih
->AvgTimePerFrame
); s
+= ss
;
108 ss
.Format(_T("\trcSource %d,%d,%d,%d\n"), vih
->rcSource
); s
+= ss
;
109 ss
.Format(_T("\trcTarget %d,%d,%d,%d\n"), vih
->rcTarget
); s
+= ss
;
110 ss
.Format(_T("\tdwInterlaceFlags 0x%x\n"), vih
->dwInterlaceFlags
); s
+= ss
;
111 ss
.Format(_T("\tdwPictAspectRatio %d:%d\n"), vih
->dwPictAspectRatioX
, vih
->dwPictAspectRatioY
); s
+= ss
;
116 DeleteMediaType(pmt
);
121 ss
.Format(_T("BITMAPINFOHEADER\n")); s
+= ss
;
122 ss
.Format(_T("\tbiCompression %x\n"), pbh
->biCompression
); s
+= ss
;
123 ss
.Format(_T("\tbiWidth %d\n"), pbh
->biWidth
); s
+= ss
;
124 ss
.Format(_T("\tbiHeight %d\n"), pbh
->biHeight
); s
+= ss
;
125 ss
.Format(_T("\tbiBitCount %d\n"), pbh
->biBitCount
); s
+= ss
;
126 ss
.Format(_T("\tbiPlanes %d\n"), pbh
->biPlanes
); s
+= ss
;
127 ss
.Format(_T("\tbiSizeImage %d\n"), pbh
->biSizeImage
); s
+= ss
;
130 DeleteMediaType(pmt
);
133 else if(size
== sizeof(AUDIO_STREAM_CONFIG_CAPS
))
139 int CountPins(IBaseFilter
* pBF
, int& nIn
, int& nOut
, int& nInC
, int& nOutC
)
144 BeginEnumPins(pBF
, pEP
, pPin
)
147 if(SUCCEEDED(pPin
->QueryDirection(&dir
)))
149 CComPtr
<IPin
> pPinConnectedTo
;
150 pPin
->ConnectedTo(&pPinConnectedTo
);
152 if(dir
== PINDIR_INPUT
) {nIn
++; if(pPinConnectedTo
) nInC
++;}
153 else if(dir
== PINDIR_OUTPUT
) {nOut
++; if(pPinConnectedTo
) nOutC
++;}
161 bool IsSplitter(IBaseFilter
* pBF
, bool fCountConnectedOnly
)
163 int nIn
, nOut
, nInC
, nOutC
;
164 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
165 return(fCountConnectedOnly
? nOutC
> 1 : nOut
> 1);
168 bool IsMultiplexer(IBaseFilter
* pBF
, bool fCountConnectedOnly
)
170 int nIn
, nOut
, nInC
, nOutC
;
171 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
172 return(fCountConnectedOnly
? nInC
> 1 : nIn
> 1);
175 bool IsStreamStart(IBaseFilter
* pBF
)
177 CComQIPtr
<IAMFilterMiscFlags
> pAMMF(pBF
);
178 if(pAMMF
&& pAMMF
->GetMiscFlags()&AM_FILTER_MISC_FLAGS_IS_SOURCE
)
181 int nIn
, nOut
, nInC
, nOutC
;
182 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
184 CComPtr
<IPin
> pIn
= GetFirstPin(pBF
);
186 || (nOut
> 0 && nIn
== 1 && pIn
&& SUCCEEDED(pIn
->ConnectionMediaType(&mt
)) && mt
.majortype
== MEDIATYPE_Stream
));
189 bool IsStreamEnd(IBaseFilter
* pBF
)
191 int nIn
, nOut
, nInC
, nOutC
;
192 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
196 bool IsVideoRenderer(IBaseFilter
* pBF
)
198 int nIn
, nOut
, nInC
, nOutC
;
199 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
201 if(nInC
> 0 && nOut
== 0)
203 BeginEnumPins(pBF
, pEP
, pPin
)
206 if(S_OK
!= pPin
->ConnectionMediaType(&mt
))
211 return(!!(mt
.majortype
== MEDIATYPE_Video
));
212 /*&& (mt.formattype == FORMAT_VideoInfo || mt.formattype == FORMAT_VideoInfo2));*/
218 memcpy(&clsid
, &GUID_NULL
, sizeof(clsid
));
219 pBF
->GetClassID(&clsid
);
221 return(clsid
== CLSID_VideoRenderer
|| clsid
== CLSID_VideoRendererDefault
);
224 #include <initguid.h>
226 DEFINE_GUID(CLSID_ReClock
,
227 0x9dc15360, 0x914c, 0x46b8, 0xb9, 0xdf, 0xbf, 0xe6, 0x7f, 0xd3, 0x6c, 0x6a);
229 bool IsAudioWaveRenderer(IBaseFilter
* pBF
)
231 int nIn
, nOut
, nInC
, nOutC
;
232 CountPins(pBF
, nIn
, nOut
, nInC
, nOutC
);
234 if(nInC
> 0 && nOut
== 0 && CComQIPtr
<IBasicAudio
>(pBF
))
236 BeginEnumPins(pBF
, pEP
, pPin
)
239 if(S_OK
!= pPin
->ConnectionMediaType(&mt
))
244 return(!!(mt
.majortype
== MEDIATYPE_Audio
)
245 /*&& mt.formattype == FORMAT_WaveFormatEx*/);
251 memcpy(&clsid
, &GUID_NULL
, sizeof(clsid
));
252 pBF
->GetClassID(&clsid
);
254 return(clsid
== CLSID_DSoundRender
|| clsid
== CLSID_AudioRender
|| clsid
== CLSID_ReClock
255 || clsid
== __uuidof(CNullAudioRenderer
) || clsid
== __uuidof(CNullUAudioRenderer
));
258 IBaseFilter
* GetUpStreamFilter(IBaseFilter
* pBF
, IPin
* pInputPin
)
260 return GetFilterFromPin(GetUpStreamPin(pBF
, pInputPin
));
263 IPin
* GetUpStreamPin(IBaseFilter
* pBF
, IPin
* pInputPin
)
265 BeginEnumPins(pBF
, pEP
, pPin
)
267 if(pInputPin
&& pInputPin
!= pPin
) continue;
270 CComPtr
<IPin
> pPinConnectedTo
;
271 if(SUCCEEDED(pPin
->QueryDirection(&dir
)) && dir
== PINDIR_INPUT
272 && SUCCEEDED(pPin
->ConnectedTo(&pPinConnectedTo
)))
274 IPin
* pRet
= pPinConnectedTo
.Detach();
284 IPin
* GetFirstPin(IBaseFilter
* pBF
, PIN_DIRECTION dir
)
286 if(!pBF
) return(NULL
);
288 BeginEnumPins(pBF
, pEP
, pPin
)
291 pPin
->QueryDirection(&dir2
);
294 IPin
* pRet
= pPin
.Detach();
304 IPin
* GetFirstDisconnectedPin(IBaseFilter
* pBF
, PIN_DIRECTION dir
)
306 if(!pBF
) return(NULL
);
308 BeginEnumPins(pBF
, pEP
, pPin
)
311 pPin
->QueryDirection(&dir2
);
312 CComPtr
<IPin
> pPinTo
;
313 if(dir
== dir2
&& (S_OK
!= pPin
->ConnectedTo(&pPinTo
)))
315 IPin
* pRet
= pPin
.Detach();
325 IBaseFilter
* FindFilter(LPCWSTR clsid
, IFilterGraph
* pFG
)
328 CLSIDFromString(CComBSTR(clsid
), &clsid2
);
329 return(FindFilter(clsid2
, pFG
));
332 IBaseFilter
* FindFilter(const CLSID
& clsid
, IFilterGraph
* pFG
)
334 BeginEnumFilters(pFG
, pEF
, pBF
)
337 if(SUCCEEDED(pBF
->GetClassID(&clsid2
)) && clsid
== clsid2
)
345 CStringW
GetFilterName(IBaseFilter
* pBF
)
349 if(pBF
&& SUCCEEDED(pBF
->QueryFilterInfo(&fi
)))
354 CStringW
GetPinName(IPin
* pPin
)
358 if(pPin
&& SUCCEEDED(pPin
->QueryPinInfo(&pi
)))
363 IFilterGraph
* GetGraphFromFilter(IBaseFilter
* pBF
)
365 if(!pBF
) return NULL
;
366 IFilterGraph
* pGraph
= NULL
;
368 if(pBF
&& SUCCEEDED(pBF
->QueryFilterInfo(&fi
)))
373 IBaseFilter
* GetFilterFromPin(IPin
* pPin
)
375 if(!pPin
) return NULL
;
376 IBaseFilter
* pBF
= NULL
;
378 if(pPin
&& SUCCEEDED(pPin
->QueryPinInfo(&pi
)))
383 IPin
* AppendFilter(IPin
* pPin
, CString DisplayName
, IGraphBuilder
* pGB
)
387 CInterfaceList
<IBaseFilter
> pFilters
;
391 if(!pPin
|| DisplayName
.IsEmpty() || !pGB
)
394 CComPtr
<IPin
> pPinTo
;
396 if(FAILED(pPin
->QueryDirection(&dir
)) || dir
!= PINDIR_OUTPUT
|| SUCCEEDED(pPin
->ConnectedTo(&pPinTo
)))
399 CComPtr
<IBindCtx
> pBindCtx
;
400 CreateBindCtx(0, &pBindCtx
);
402 CComPtr
<IMoniker
> pMoniker
;
404 if(S_OK
!= MkParseDisplayName(pBindCtx
, CComBSTR(DisplayName
), &chEaten
, &pMoniker
))
407 CComPtr
<IBaseFilter
> pBF
;
408 if(FAILED(pMoniker
->BindToObject(pBindCtx
, 0, IID_IBaseFilter
, (void**)&pBF
)) || !pBF
)
411 CComPtr
<IPropertyBag
> pPB
;
412 if(FAILED(pMoniker
->BindToStorage(pBindCtx
, 0, IID_IPropertyBag
, (void**)&pPB
)))
416 if(FAILED(pPB
->Read(CComBSTR(_T("FriendlyName")), &var
, NULL
)))
419 pFilters
.AddTail(pBF
);
420 BeginEnumFilters(pGB
, pEnum
, pBF2
)
421 pFilters
.AddTail(pBF2
);
424 if(FAILED(pGB
->AddFilter(pBF
, CStringW(var
.bstrVal
))))
427 BeginEnumFilters(pGB
, pEnum
, pBF2
)
428 if(!pFilters
.Find(pBF2
) && SUCCEEDED(pGB
->RemoveFilter(pBF2
)))
432 pPinTo
= GetFirstPin(pBF
, PINDIR_INPUT
);
435 pGB
->RemoveFilter(pBF
);
440 if(FAILED(hr
= pGB
->ConnectDirect(pPin
, pPinTo
, NULL
)))
442 hr
= pGB
->Connect(pPin
, pPinTo
);
443 pGB
->RemoveFilter(pBF
);
447 BeginEnumFilters(pGB
, pEnum
, pBF2
)
448 if(!pFilters
.Find(pBF2
) && SUCCEEDED(pGB
->RemoveFilter(pBF2
)))
452 pRet
= GetFirstPin(pBF
, PINDIR_OUTPUT
);
456 pGB
->RemoveFilter(pBF
);
465 IPin
* InsertFilter(IPin
* pPin
, CString DisplayName
, IGraphBuilder
* pGB
)
469 if(!pPin
|| DisplayName
.IsEmpty() || !pGB
)
473 if(FAILED(pPin
->QueryDirection(&dir
)))
476 CComPtr
<IPin
> pFrom
, pTo
;
478 if(dir
== PINDIR_INPUT
)
480 pPin
->ConnectedTo(&pFrom
);
483 else if(dir
== PINDIR_OUTPUT
)
486 pPin
->ConnectedTo(&pTo
);
492 CComPtr
<IBindCtx
> pBindCtx
;
493 CreateBindCtx(0, &pBindCtx
);
495 CComPtr
<IMoniker
> pMoniker
;
497 if(S_OK
!= MkParseDisplayName(pBindCtx
, CComBSTR(DisplayName
), &chEaten
, &pMoniker
))
500 CComPtr
<IBaseFilter
> pBF
;
501 if(FAILED(pMoniker
->BindToObject(pBindCtx
, 0, IID_IBaseFilter
, (void**)&pBF
)) || !pBF
)
504 CComPtr
<IPropertyBag
> pPB
;
505 if(FAILED(pMoniker
->BindToStorage(pBindCtx
, 0, IID_IPropertyBag
, (void**)&pPB
)))
509 if(FAILED(pPB
->Read(CComBSTR(_T("FriendlyName")), &var
, NULL
)))
512 if(FAILED(pGB
->AddFilter(pBF
, CStringW(var
.bstrVal
))))
515 CComPtr
<IPin
> pFromTo
= GetFirstPin(pBF
, PINDIR_INPUT
);
518 pGB
->RemoveFilter(pBF
);
522 if(FAILED(pGB
->Disconnect(pFrom
)) || FAILED(pGB
->Disconnect(pTo
)))
524 pGB
->RemoveFilter(pBF
);
525 pGB
->ConnectDirect(pFrom
, pTo
, NULL
);
530 if(FAILED(hr
= pGB
->ConnectDirect(pFrom
, pFromTo
, NULL
)))
532 pGB
->RemoveFilter(pBF
);
533 pGB
->ConnectDirect(pFrom
, pTo
, NULL
);
537 CComPtr
<IPin
> pToFrom
= GetFirstPin(pBF
, PINDIR_OUTPUT
);
540 pGB
->RemoveFilter(pBF
);
541 pGB
->ConnectDirect(pFrom
, pTo
, NULL
);
545 if(FAILED(pGB
->ConnectDirect(pToFrom
, pTo
, NULL
)))
547 pGB
->RemoveFilter(pBF
);
548 pGB
->ConnectDirect(pFrom
, pTo
, NULL
);
559 void ExtractMediaTypes(IPin
* pPin
, CAtlArray
<GUID
>& types
)
563 BeginEnumMediaTypes(pPin
, pEM
, pmt
)
567 for(int i
= 0; !fFound
&& i
< types
.GetCount(); i
+= 2)
569 if(types
[i
] == pmt
->majortype
&& types
[i
+1] == pmt
->subtype
)
575 types
.Add(pmt
->majortype
);
576 types
.Add(pmt
->subtype
);
579 EndEnumMediaTypes(pmt
)
582 void ExtractMediaTypes(IPin
* pPin
, CAtlList
<CMediaType
>& mts
)
586 BeginEnumMediaTypes(pPin
, pEM
, pmt
)
590 POSITION pos
= mts
.GetHeadPosition();
591 while(!fFound
&& pos
)
593 CMediaType
& mt
= mts
.GetNext(pos
);
594 if(mt
.majortype
== pmt
->majortype
&& mt
.subtype
== pmt
->subtype
)
600 mts
.AddTail(CMediaType(*pmt
));
603 EndEnumMediaTypes(pmt
)
606 int Eval_Exception(int n_except
)
608 if(n_except
== STATUS_ACCESS_VIOLATION
)
610 AfxMessageBox(_T("The property page of this filter has just caused a\nmemory access violation. The application will gently die now :)"));
613 return EXCEPTION_CONTINUE_SEARCH
;
616 void MyOleCreatePropertyFrame(HWND hwndOwner
, UINT x
, UINT y
, LPCOLESTR lpszCaption
, ULONG cObjects
, LPUNKNOWN FAR
* lplpUnk
, ULONG cPages
, LPCLSID lpPageClsID
, LCID lcid
, DWORD dwReserved
, LPVOID lpvReserved
)
620 OleCreatePropertyFrame(hwndOwner
, x
, y
, lpszCaption
, cObjects
, lplpUnk
, cPages
, lpPageClsID
, lcid
, dwReserved
, lpvReserved
);
622 __except(Eval_Exception(GetExceptionCode()))
624 // No code; this block never executed.
628 void ShowPPage(CString DisplayName
, HWND hParentWnd
)
630 CComPtr
<IBindCtx
> pBindCtx
;
631 CreateBindCtx(0, &pBindCtx
);
633 CComPtr
<IMoniker
> pMoniker
;
635 if(S_OK
!= MkParseDisplayName(pBindCtx
, CStringW(DisplayName
), &chEaten
, &pMoniker
))
638 CComPtr
<IBaseFilter
> pBF
;
639 if(FAILED(pMoniker
->BindToObject(pBindCtx
, 0, IID_IBaseFilter
, (void**)&pBF
)) || !pBF
)
642 ShowPPage(pBF
, hParentWnd
);
645 void ShowPPage(IUnknown
* pUnk
, HWND hParentWnd
)
647 CComQIPtr
<ISpecifyPropertyPages
> pSPP
= pUnk
;
652 CComQIPtr
<IBaseFilter
> pBF
= pSPP
;
654 CComQIPtr
<IPin
> pPin
= pSPP
;
656 if(pBF
&& SUCCEEDED(pBF
->QueryFilterInfo(&fi
)))
658 else if(pPin
&& SUCCEEDED(pPin
->QueryPinInfo(&pi
)))
662 caGUID
.pElems
= NULL
;
663 if(SUCCEEDED(pSPP
->GetPages(&caGUID
)))
665 IUnknown
* lpUnk
= NULL
;
666 pSPP
.QueryInterface(&lpUnk
);
667 MyOleCreatePropertyFrame(
668 hParentWnd
, 0, 0, CStringW(str
),
669 1, (IUnknown
**)&lpUnk
,
670 caGUID
.cElems
, caGUID
.pElems
,
674 if(caGUID
.pElems
) CoTaskMemFree(caGUID
.pElems
);
678 CLSID
GetCLSID(IBaseFilter
* pBF
)
680 CLSID clsid
= GUID_NULL
;
681 if(pBF
) pBF
->GetClassID(&clsid
);
685 CLSID
GetCLSID(IPin
* pPin
)
687 return(GetCLSID(GetFilterFromPin(pPin
)));
690 bool IsCLSIDRegistered(LPCTSTR clsid
)
692 CString
rootkey1(_T("CLSID\\"));
693 CString
rootkey2(_T("CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\Instance\\"));
695 return ERROR_SUCCESS
== CRegKey().Open(HKEY_CLASSES_ROOT
, rootkey1
+ clsid
, KEY_READ
)
696 || ERROR_SUCCESS
== CRegKey().Open(HKEY_CLASSES_ROOT
, rootkey2
+ clsid
, KEY_READ
);
699 bool IsCLSIDRegistered(const CLSID
& clsid
)
703 LPOLESTR pStr
= NULL
;
704 if(S_OK
== StringFromCLSID(clsid
, &pStr
) && pStr
)
706 fRet
= IsCLSIDRegistered(CString(pStr
));
713 void CStringToBin(CString str
, CAtlArray
<BYTE
>& data
)
716 ASSERT((str
.GetLength()&1) == 0);
717 data
.SetCount(str
.GetLength()/2);
722 for(int i
= 0, j
= str
.GetLength(); i
< j
; i
++)
725 if(c
>= '0' && c
<= '9')
727 if(!(i
&1)) b
= ((char(c
-'0')<<4)&0xf0)|(b
&0x0f);
728 else b
= (char(c
-'0')&0x0f)|(b
&0xf0);
730 else if(c
>= 'A' && c
<= 'F')
732 if(!(i
&1)) b
= ((char(c
-'A'+10)<<4)&0xf0)|(b
&0x0f);
733 else b
= (char(c
-'A'+10)&0x0f)|(b
&0xf0);
745 CString
BinToCString(BYTE
* ptr
, int len
)
752 high
= (*ptr
>>4) >= 10 ? (*ptr
>>4)-10 + 'A' : (*ptr
>>4) + '0';
753 low
= (*ptr
&0xf) >= 10 ? (*ptr
&0xf)-10 + 'A' : (*ptr
&0xf) + '0';
756 str
.Format(_T("%c%c"), high
, low
);
765 static void FindFiles(CString fn
, CAtlList
<CString
>& files
)
768 path
.Replace('/', '\\');
769 path
= path
.Left(path
.ReverseFind('\\')+1);
771 WIN32_FIND_DATA findData
;
772 HANDLE h
= FindFirstFile(fn
, &findData
);
773 if(h
!= INVALID_HANDLE_VALUE
)
775 do {files
.AddTail(path
+ findData
.cFileName
);}
776 while(FindNextFile(h
, &findData
));
782 cdrom_t
GetCDROMType(TCHAR drive
, CAtlList
<CString
>& files
)
787 path
.Format(_T("%c:"), drive
);
789 if(GetDriveType(path
+ _T("\\")) == DRIVE_CDROM
)
792 FindFiles(path
+ _T("\\mpegav\\avseq??.dat"), files
);
793 FindFiles(path
+ _T("\\mpegav\\avseq??.mpg"), files
);
794 FindFiles(path
+ _T("\\mpeg2\\avseq??.dat"), files
);
795 FindFiles(path
+ _T("\\mpeg2\\avseq??.mpg"), files
);
796 FindFiles(path
+ _T("\\mpegav\\music??.dat"), files
);
797 FindFiles(path
+ _T("\\mpegav\\music??.mpg"), files
);
798 FindFiles(path
+ _T("\\mpeg2\\music??.dat"), files
);
799 FindFiles(path
+ _T("\\mpeg2\\music??.mpg"), files
);
800 if(files
.GetCount() > 0) return CDROM_VideoCD
;
803 FindFiles(path
+ _T("\\VIDEO_TS\\video_ts.ifo"), files
);
804 if(files
.GetCount() > 0) return CDROM_DVDVideo
;
807 if(!(GetVersion()&0x80000000))
809 HANDLE hDrive
= CreateFile(CString(_T("\\\\.\\")) + path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
810 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, (HANDLE
)NULL
);
811 if(hDrive
!= INVALID_HANDLE_VALUE
)
815 if(DeviceIoControl(hDrive
, IOCTL_CDROM_READ_TOC
, NULL
, 0, &TOC
, sizeof(TOC
), &BytesReturned
, 0))
817 for(int i
= TOC
.FirstTrack
; i
<= TOC
.LastTrack
; i
++)
819 // MMC-3 Draft Revision 10g: Table 222 ?Q Sub-channel control field
820 TOC
.TrackData
[i
-1].Control
&= 5;
821 if(TOC
.TrackData
[i
-1].Control
== 0 || TOC
.TrackData
[i
-1].Control
== 1)
824 fn
.Format(_T("%s\\track%02d.cda"), path
, i
);
833 if(files
.GetCount() > 0) return CDROM_Audio
;
835 // it is a cdrom but nothing special
836 return CDROM_Unknown
;
839 return CDROM_NotFound
;
842 CString
GetDriveLabel(TCHAR drive
)
847 path
.Format(_T("%c:\\"), drive
);
848 TCHAR VolumeNameBuffer
[MAX_PATH
], FileSystemNameBuffer
[MAX_PATH
];
849 DWORD VolumeSerialNumber
, MaximumComponentLength
, FileSystemFlags
;
850 if(GetVolumeInformation(path
,
851 VolumeNameBuffer
, MAX_PATH
, &VolumeSerialNumber
, &MaximumComponentLength
,
852 &FileSystemFlags
, FileSystemNameBuffer
, MAX_PATH
))
854 label
= VolumeNameBuffer
;
860 bool GetKeyFrames(CString fn
, CUIntArray
& kfs
)
864 CString fn2
= CString(fn
).MakeLower();
865 if(fn2
.Mid(fn2
.ReverseFind('.')+1) == _T("avi"))
870 if(AVIFileOpen(&pfile
, fn
, OF_SHARE_DENY_WRITE
, 0L) == 0)
873 memset(&afi
, 0, sizeof(afi
));
874 AVIFileInfo(pfile
, &afi
, sizeof(AVIFILEINFO
));
876 CComPtr
<IAVIStream
> pavi
;
877 if(AVIFileGetStream(pfile
, &pavi
, streamtypeVIDEO
, 0) == AVIERR_OK
)
880 AVIStreamInfo(pavi
, &si
, sizeof(si
));
882 if(afi
.dwCaps
&AVIFILECAPS_ALLKEYFRAMES
)
884 kfs
.SetSize(si
.dwLength
);
885 for(int kf
= 0; kf
< si
.dwLength
; kf
++) kfs
[kf
] = kf
;
889 for(int kf
= 0; ; kf
++)
891 kf
= pavi
->FindSample(kf
, FIND_KEY
|FIND_NEXT
);
892 if(kf
< 0 || kfs
.GetCount() > 0 && kfs
[kfs
.GetCount()-1] >= kf
) break;
896 if(kfs
.GetCount() > 0 && kfs
[kfs
.GetCount()-1] < si
.dwLength
-1)
898 kfs
.Add(si
.dwLength
-1);
903 AVIFileRelease(pfile
);
909 return(kfs
.GetCount() > 0);
912 DVD_HMSF_TIMECODE
RT2HMSF(REFERENCE_TIME rt
, double fps
)
914 DVD_HMSF_TIMECODE hmsf
=
916 (BYTE
)((rt
/10000000/60/60)),
917 (BYTE
)((rt
/10000000/60)%60),
918 (BYTE
)((rt
/10000000)%60),
919 (BYTE
)(1.0*((rt
/10000)%1000) * fps
/ 1000)
925 REFERENCE_TIME
HMSF2RT(DVD_HMSF_TIMECODE hmsf
, double fps
)
927 if(fps
== 0) {hmsf
.bFrames
= 0; fps
= 1;}
928 return (REFERENCE_TIME
)((((REFERENCE_TIME
)hmsf
.bHours
*60+hmsf
.bMinutes
)*60+hmsf
.bSeconds
)*1000+1.0*hmsf
.bFrames
*1000/fps
)*10000;
931 void memsetd(void* dst
, unsigned int c
, size_t nbytes
)
934 if (!(g_cpuid
.m_flags
& g_cpuid
.sse2
)) {
946 size_t n
= nbytes
/ 4;
947 size_t o
= n
- (n
% 4);
949 __m128i val
= _mm_set1_epi32 ( (int)c
);
950 if (((uintptr_t)dst
& 0x0F) == 0) { // 16-byte aligned
951 for (size_t i
= 0; i
< o
; i
+=4) {
952 _mm_store_si128( (__m128i
*)&(((DWORD
*)dst
)[i
]), val
);
955 for (size_t i
= 0; i
< o
; i
+=4) {
956 _mm_storeu_si128( (__m128i
*)&(((DWORD
*)dst
)[i
]), val
);
962 ((DWORD
*)dst
)[o
+ 2] = c
;
964 ((DWORD
*)dst
)[o
+ 1] = c
;
966 ((DWORD
*)dst
)[o
+ 0] = c
;
970 void memsetw(void* dst
, unsigned short c
, size_t nbytes
)
972 memsetd(dst
, c
<< 16 | c
, nbytes
);
974 size_t n
= nbytes
/ 2;
975 size_t o
= (n
/ 2) * 2;
981 bool ExtractBIH(const AM_MEDIA_TYPE
* pmt
, BITMAPINFOHEADER
* bih
)
985 memset(bih
, 0, sizeof(*bih
));
987 if(pmt
->formattype
== FORMAT_VideoInfo
)
989 VIDEOINFOHEADER
* vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
990 memcpy(bih
, &vih
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
993 else if(pmt
->formattype
== FORMAT_VideoInfo2
)
995 VIDEOINFOHEADER2
* vih
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
996 memcpy(bih
, &vih
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
999 else if(pmt
->formattype
== FORMAT_MPEGVideo
)
1001 VIDEOINFOHEADER
* vih
= &((MPEG1VIDEOINFO
*)pmt
->pbFormat
)->hdr
;
1002 memcpy(bih
, &vih
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1005 else if(pmt
->formattype
== FORMAT_MPEG2_VIDEO
)
1007 VIDEOINFOHEADER2
* vih
= &((MPEG2VIDEOINFO
*)pmt
->pbFormat
)->hdr
;
1008 memcpy(bih
, &vih
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1011 else if(pmt
->formattype
== FORMAT_DiracVideoInfo
)
1013 VIDEOINFOHEADER2
* vih
= &((DIRACINFOHEADER
*)pmt
->pbFormat
)->hdr
;
1014 memcpy(bih
, &vih
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1022 bool ExtractBIH(IMediaSample
* pMS
, BITMAPINFOHEADER
* bih
)
1024 AM_MEDIA_TYPE
* pmt
= NULL
;
1025 pMS
->GetMediaType(&pmt
);
1028 bool fRet
= ExtractBIH(pmt
, bih
);
1029 DeleteMediaType(pmt
);
1036 bool ExtractDim(const AM_MEDIA_TYPE
* pmt
, int& w
, int& h
, int& arx
, int& ary
)
1038 w
= h
= arx
= ary
= 0;
1040 if(pmt
->formattype
== FORMAT_VideoInfo
|| pmt
->formattype
== FORMAT_MPEGVideo
)
1042 VIDEOINFOHEADER
* vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
1043 w
= vih
->bmiHeader
.biWidth
;
1044 h
= abs(vih
->bmiHeader
.biHeight
);
1045 arx
= w
* vih
->bmiHeader
.biYPelsPerMeter
;
1046 ary
= h
* vih
->bmiHeader
.biXPelsPerMeter
;
1048 else if(pmt
->formattype
== FORMAT_VideoInfo2
|| pmt
->formattype
== FORMAT_MPEG2_VIDEO
|| pmt
->formattype
== FORMAT_DiracVideoInfo
)
1050 VIDEOINFOHEADER2
* vih
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
1051 w
= vih
->bmiHeader
.biWidth
;
1052 h
= abs(vih
->bmiHeader
.biHeight
);
1053 arx
= vih
->dwPictAspectRatioX
;
1054 ary
= vih
->dwPictAspectRatioY
;
1070 if(pmt
->formattype
== FORMAT_MPEGVideo
)
1072 ptr
= ((MPEG1VIDEOINFO
*)pmt
->pbFormat
)->bSequenceHeader
;
1073 len
= ((MPEG1VIDEOINFO
*)pmt
->pbFormat
)->cbSequenceHeader
;
1075 if(ptr
&& len
>= 8 && *(DWORD
*)ptr
== 0xb3010000)
1077 w
= (ptr
[4]<<4)|(ptr
[5]>>4);
1078 h
= ((ptr
[5]&0xf)<<8)|ptr
[6];
1081 1.0000f
,1.0000f
,0.6735f
,0.7031f
,
1082 0.7615f
,0.8055f
,0.8437f
,0.8935f
,
1083 0.9157f
,0.9815f
,1.0255f
,1.0695f
,
1084 1.0950f
,1.1575f
,1.2015f
,1.0000f
,
1086 arx
= (int)((float)w
/ ar
[ptr
[7]>>4] + 0.5);
1090 else if(pmt
->formattype
== FORMAT_MPEG2_VIDEO
)
1092 ptr
= (BYTE
*)((MPEG2VIDEOINFO
*)pmt
->pbFormat
)->dwSequenceHeader
;
1093 len
= ((MPEG2VIDEOINFO
*)pmt
->pbFormat
)->cbSequenceHeader
;
1095 if(ptr
&& len
>= 8 && *(DWORD
*)ptr
== 0xb3010000)
1097 w
= (ptr
[4]<<4)|(ptr
[5]>>4);
1098 h
= ((ptr
[5]&0xf)<<8)|ptr
[6];
1099 struct {int x
, y
;} ar
[] = {{w
,h
},{4,3},{16,9},{221,100},{w
,h
}};
1100 int i
= min(max(ptr
[7]>>4, 1), 5)-1;
1111 DWORD a
= arx
, b
= ary
;
1112 while(a
) {int tmp
= a
; a
= b
% tmp
; b
= tmp
;}
1113 if(b
) arx
/= b
, ary
/= b
;
1118 bool MakeMPEG2MediaType(CMediaType
& mt
, BYTE
* seqhdr
, DWORD len
, int w
, int h
)
1120 if(len
< 4 || *(DWORD
*)seqhdr
!= 0xb3010000) return false;
1122 BYTE
* seqhdr_ext
= NULL
;
1124 BYTE
* seqhdr_end
= seqhdr
+ 11;
1125 if(seqhdr_end
- seqhdr
> len
) return false;
1126 if(*seqhdr_end
& 0x02) seqhdr_end
+= 64;
1127 if(seqhdr_end
- seqhdr
> len
) return false;
1128 if(*seqhdr_end
& 0x01) seqhdr_end
+= 64;
1129 if(seqhdr_end
- seqhdr
> len
) return false;
1131 if(seqhdr_end
- seqhdr
> len
) return false;
1132 if(len
- (seqhdr_end
- seqhdr
) > 4 && *(DWORD
*)seqhdr_end
== 0xb5010000) {seqhdr_ext
= seqhdr_end
; seqhdr_end
+= 10;}
1133 if(seqhdr_end
- seqhdr
> len
) return false;
1135 len
= seqhdr_end
- seqhdr
;
1139 mt
.majortype
= MEDIATYPE_Video
;
1140 mt
.subtype
= MEDIASUBTYPE_MPEG2_VIDEO
;
1141 mt
.formattype
= FORMAT_MPEG2Video
;
1143 MPEG2VIDEOINFO
* vih
= (MPEG2VIDEOINFO
*)mt
.AllocFormatBuffer(FIELD_OFFSET(MPEG2VIDEOINFO
, dwSequenceHeader
) + len
);
1144 memset(mt
.Format(), 0, mt
.FormatLength());
1145 vih
->hdr
.bmiHeader
.biSize
= sizeof(vih
->hdr
.bmiHeader
);
1146 vih
->hdr
.bmiHeader
.biWidth
= w
;
1147 vih
->hdr
.bmiHeader
.biHeight
= h
;
1149 BYTE
* pSequenceHeader
= (BYTE
*)vih
->dwSequenceHeader
;
1150 memcpy(pSequenceHeader
, seqhdr
, len
);
1151 vih
->cbSequenceHeader
= len
;
1153 static char profile
[8] =
1155 0, AM_MPEG2Profile_High
, AM_MPEG2Profile_SpatiallyScalable
, AM_MPEG2Profile_SNRScalable
,
1156 AM_MPEG2Profile_Main
, AM_MPEG2Profile_Simple
, 0, 0
1159 static char level
[16] =
1162 AM_MPEG2Level_High
, 0, AM_MPEG2Level_High1440
, 0,
1163 AM_MPEG2Level_Main
, 0, AM_MPEG2Level_Low
, 0,
1167 if(seqhdr_ext
&& (seqhdr_ext
[4] & 0xf0) == 0x10)
1169 vih
->dwProfile
= profile
[seqhdr_ext
[4] & 0x07];
1170 vih
->dwLevel
= level
[seqhdr_ext
[5] >> 4];
1176 unsigned __int64
GetFileVersion(LPCTSTR fn
)
1178 unsigned __int64 ret
= 0;
1181 VS_FIXEDFILEINFO
* pvsf
= (VS_FIXEDFILEINFO
*)buff
;
1182 DWORD d
; // a variable that GetFileVersionInfoSize sets to zero (but why is it needed ?????????????????????????????? :)
1183 DWORD len
= GetFileVersionInfoSize((TCHAR
*)fn
, &d
);
1187 TCHAR
* b1
= new TCHAR
[len
];
1191 if(GetFileVersionInfo((TCHAR
*)fn
, 0, len
, b1
) && VerQueryValue(b1
, _T("\\"), (void**)&pvsf
, &uLen
))
1193 ret
= ((unsigned __int64
)pvsf
->dwFileVersionMS
<<32) | pvsf
->dwFileVersionLS
;
1203 bool CreateFilter(CStringW DisplayName
, IBaseFilter
** ppBF
, CStringW
& FriendlyName
)
1205 if(!ppBF
) return(false);
1208 FriendlyName
.Empty();
1210 CComPtr
<IBindCtx
> pBindCtx
;
1211 CreateBindCtx(0, &pBindCtx
);
1213 CComPtr
<IMoniker
> pMoniker
;
1215 if(S_OK
!= MkParseDisplayName(pBindCtx
, CComBSTR(DisplayName
), &chEaten
, &pMoniker
))
1218 if(FAILED(pMoniker
->BindToObject(pBindCtx
, 0, IID_IBaseFilter
, (void**)ppBF
)) || !*ppBF
)
1221 CComPtr
<IPropertyBag
> pPB
;
1223 if(SUCCEEDED(pMoniker
->BindToStorage(pBindCtx
, 0, IID_IPropertyBag
, (void**)&pPB
))
1224 && SUCCEEDED(pPB
->Read(CComBSTR(_T("FriendlyName")), &var
, NULL
)))
1225 FriendlyName
= var
.bstrVal
;
1230 IBaseFilter
* AppendFilter(IPin
* pPin
, IMoniker
* pMoniker
, IGraphBuilder
* pGB
)
1234 if(!pPin
|| !pMoniker
|| !pGB
)
1237 CComPtr
<IPin
> pPinTo
;
1239 if(FAILED(pPin
->QueryDirection(&dir
)) || dir
!= PINDIR_OUTPUT
|| SUCCEEDED(pPin
->ConnectedTo(&pPinTo
)))
1242 CComPtr
<IBindCtx
> pBindCtx
;
1243 CreateBindCtx(0, &pBindCtx
);
1245 CComPtr
<IPropertyBag
> pPB
;
1246 if(FAILED(pMoniker
->BindToStorage(pBindCtx
, 0, IID_IPropertyBag
, (void**)&pPB
)))
1250 if(FAILED(pPB
->Read(CComBSTR(_T("FriendlyName")), &var
, NULL
)))
1253 CComPtr
<IBaseFilter
> pBF
;
1254 if(FAILED(pMoniker
->BindToObject(pBindCtx
, 0, IID_IBaseFilter
, (void**)&pBF
)) || !pBF
)
1257 if(FAILED(pGB
->AddFilter(pBF
, CStringW(var
.bstrVal
))))
1260 BeginEnumPins(pBF
, pEP
, pPinTo
)
1263 if(FAILED(pPinTo
->QueryDirection(&dir
)) || dir
!= PINDIR_INPUT
)
1266 if(SUCCEEDED(pGB
->ConnectDirect(pPin
, pPinTo
, NULL
)))
1271 pGB
->RemoveFilter(pBF
);
1278 CStringW
GetFriendlyName(CStringW DisplayName
)
1280 CStringW FriendlyName
;
1282 CComPtr
<IBindCtx
> pBindCtx
;
1283 CreateBindCtx(0, &pBindCtx
);
1285 CComPtr
<IMoniker
> pMoniker
;
1287 if(S_OK
!= MkParseDisplayName(pBindCtx
, CComBSTR(DisplayName
), &chEaten
, &pMoniker
))
1290 CComPtr
<IPropertyBag
> pPB
;
1292 if(SUCCEEDED(pMoniker
->BindToStorage(pBindCtx
, 0, IID_IPropertyBag
, (void**)&pPB
))
1293 && SUCCEEDED(pPB
->Read(CComBSTR(_T("FriendlyName")), &var
, NULL
)))
1294 FriendlyName
= var
.bstrVal
;
1296 return FriendlyName
;
1306 static CAtlList
<ExternalObject
> s_extobjs
;
1308 HRESULT
LoadExternalObject(LPCTSTR path
, REFCLSID clsid
, REFIID iid
, void** ppv
)
1310 CheckPointer(ppv
, E_POINTER
);
1312 CString fullpath
= MakeFullPath(path
);
1314 HINSTANCE hInst
= NULL
;
1315 bool fFound
= false;
1317 POSITION pos
= s_extobjs
.GetHeadPosition();
1320 ExternalObject
& eo
= s_extobjs
.GetNext(pos
);
1321 if(!eo
.path
.CompareNoCase(fullpath
))
1329 HRESULT hr
= E_FAIL
;
1331 if(hInst
|| (hInst
= CoLoadLibrary(CComBSTR(fullpath
), TRUE
)))
1333 typedef HRESULT (__stdcall
* PDllGetClassObject
)(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
);
1334 PDllGetClassObject p
= (PDllGetClassObject
)GetProcAddress(hInst
, "DllGetClassObject");
1336 if(p
&& FAILED(hr
= p(clsid
, iid
, ppv
)))
1338 CComPtr
<IClassFactory
> pCF
;
1339 if(SUCCEEDED(hr
= p(clsid
, __uuidof(IClassFactory
), (void**)&pCF
)))
1341 hr
= pCF
->CreateInstance(NULL
, iid
, ppv
);
1346 if(FAILED(hr
) && hInst
&& !fFound
)
1348 CoFreeLibrary(hInst
);
1352 if(hInst
&& !fFound
)
1358 s_extobjs
.AddTail(eo
);
1364 HRESULT
LoadExternalFilter(LPCTSTR path
, REFCLSID clsid
, IBaseFilter
** ppBF
)
1366 return LoadExternalObject(path
, clsid
, __uuidof(IBaseFilter
), (void**)ppBF
);
1369 HRESULT
LoadExternalPropertyPage(IPersist
* pP
, REFCLSID clsid
, IPropertyPage
** ppPP
)
1371 CLSID clsid2
= GUID_NULL
;
1372 if(FAILED(pP
->GetClassID(&clsid2
))) return E_FAIL
;
1374 POSITION pos
= s_extobjs
.GetHeadPosition();
1377 ExternalObject
& eo
= s_extobjs
.GetNext(pos
);
1378 if(eo
.clsid
== clsid2
)
1380 return LoadExternalObject(eo
.path
, clsid
, __uuidof(IPropertyPage
), (void**)ppPP
);
1387 void UnloadExternalObjects()
1389 POSITION pos
= s_extobjs
.GetHeadPosition();
1392 ExternalObject
& eo
= s_extobjs
.GetNext(pos
);
1393 CoFreeLibrary(eo
.hInst
);
1395 s_extobjs
.RemoveAll();
1398 CString
MakeFullPath(LPCTSTR path
)
1401 full
.Replace('/', '\\');
1404 fn
.ReleaseBuffer(GetModuleFileName(AfxGetInstanceHandle(), fn
.GetBuffer(MAX_PATH
), MAX_PATH
));
1407 if(full
.GetLength() >= 2 && full
[0] == '\\' && full
[1] != '\\')
1410 full
= CString(p
) + full
.Mid(1);
1412 else if(full
.Find(_T(":\\")) < 0)
1416 full
= CString(p
) + full
;
1426 CString
GetMediaTypeName(const GUID
& guid
)
1428 CString ret
= guid
== GUID_NULL
1430 : CString(GuidNames
[guid
]);
1432 if(ret
== _T("FOURCC GUID"))
1435 if(guid
.Data1
>= 0x10000)
1436 str
.Format(_T("Video: %c%c%c%c"), (guid
.Data1
>>0)&0xff, (guid
.Data1
>>8)&0xff, (guid
.Data1
>>16)&0xff, (guid
.Data1
>>24)&0xff);
1438 str
.Format(_T("Audio: 0x%08x"), guid
.Data1
);
1441 else if(ret
== _T("Unknown GUID Name"))
1443 WCHAR null
[128] = {0}, buff
[128];
1444 StringFromGUID2(GUID_NULL
, null
, 127);
1445 ret
= CString(CStringW(StringFromGUID2(guid
, buff
, 127) ? buff
: null
));
1451 GUID
GUIDFromCString(CString str
)
1453 GUID guid
= GUID_NULL
;
1454 HRESULT hr
= CLSIDFromString(CComBSTR(str
), &guid
);
1455 ASSERT(SUCCEEDED(hr
));
1459 HRESULT
GUIDFromCString(CString str
, GUID
& guid
)
1462 return CLSIDFromString(CComBSTR(str
), &guid
);
1465 CString
CStringFromGUID(const GUID
& guid
)
1467 WCHAR null
[128] = {0}, buff
[128];
1468 StringFromGUID2(GUID_NULL
, null
, 127);
1469 return CString(StringFromGUID2(guid
, buff
, 127) > 0 ? buff
: null
);
1472 CStringW
UTF8To16(LPCSTR utf8
)
1475 int n
= MultiByteToWideChar(CP_UTF8
, 0, utf8
, -1, NULL
, 0)-1;
1476 if(n
< 0) return str
;
1477 str
.ReleaseBuffer(MultiByteToWideChar(CP_UTF8
, 0, utf8
, -1, str
.GetBuffer(n
), n
+1)-1);
1481 CStringA
UTF16To8(LPCWSTR utf16
)
1484 int n
= WideCharToMultiByte(CP_UTF8
, 0, utf16
, -1, NULL
, 0, NULL
, NULL
)-1;
1485 if(n
< 0) return str
;
1486 str
.ReleaseBuffer(WideCharToMultiByte(CP_UTF8
, 0, utf16
, -1, str
.GetBuffer(n
), n
+1, NULL
, NULL
)-1);
1491 LPCSTR name
, iso6392
, iso6391
;
1493 } s_isolangs
[] = { // TODO : fill LCID !!!
1494 {"Abkhazian", "abk", "ab"},
1495 {"Achinese", "ace", ""},
1496 {"Acoli", "ach", ""},
1497 {"Adangme", "ada", ""},
1498 {"Afar", "aar", "aa"},
1499 {"Afrihili", "afh", ""},
1500 {"Afrikaans", "afr", "af", MAKELCID( MAKELANGID(LANG_AFRIKAANS
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1501 {"Afro-Asiatic (Other)", "afa", ""},
1502 {"Akan", "aka", "ak"},
1503 {"Akkadian", "akk", ""},
1504 {"Albanian", "alb", "sq"},
1505 {"Albanian", "sqi", "sq", MAKELCID( MAKELANGID(LANG_ALBANIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1506 {"Aleut", "ale", ""},
1507 {"Algonquian languages", "alg", ""},
1508 {"Altaic (Other)", "tut", ""},
1509 {"Amharic", "amh", "am"},
1510 {"Apache languages", "apa", ""},
1511 {"Arabic", "ara", "ar", MAKELCID( MAKELANGID(LANG_ARABIC
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1512 {"Aragonese", "arg", "an"},
1513 {"Aramaic", "arc", ""},
1514 {"Arapaho", "arp", ""},
1515 {"Araucanian", "arn", ""},
1516 {"Arawak", "arw", ""},
1517 {"Armenian", "arm", "hy", MAKELCID( MAKELANGID(LANG_ARMENIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1518 {"Armenian", "hye", "hy", MAKELCID( MAKELANGID(LANG_ARMENIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1519 {"Artificial (Other)", "art", ""},
1520 {"Assamese", "asm", "as", MAKELCID( MAKELANGID(LANG_ASSAMESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1521 {"Asturian; Bable", "ast", ""},
1522 {"Athapascan languages", "ath", ""},
1523 {"Australian languages", "aus", ""},
1524 {"Austronesian (Other)", "map", ""},
1525 {"Avaric", "ava", "av"},
1526 {"Avestan", "ave", "ae"},
1527 {"Awadhi", "awa", ""},
1528 {"Aymara", "aym", "ay"},
1529 {"Azerbaijani", "aze", "az", MAKELCID( MAKELANGID(LANG_AZERI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1530 {"Bable; Asturian", "ast", ""},
1531 {"Balinese", "ban", ""},
1532 {"Baltic (Other)", "bat", ""},
1533 {"Baluchi", "bal", ""},
1534 {"Bambara", "bam", "bm"},
1535 {"Bamileke languages", "bai", ""},
1536 {"Banda", "bad", ""},
1537 {"Bantu (Other)", "bnt", ""},
1538 {"Basa", "bas", ""},
1539 {"Bashkir", "bak", "ba", MAKELCID( MAKELANGID(LANG_BASHKIR
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1540 {"Basque", "baq", "eu", MAKELCID( MAKELANGID(LANG_BASQUE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1541 {"Basque", "eus", "eu", MAKELCID( MAKELANGID(LANG_BASQUE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1542 {"Batak (Indonesia)", "btk", ""},
1543 {"Beja", "bej", ""},
1544 {"Belarusian", "bel", "be", MAKELCID( MAKELANGID(LANG_BELARUSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1545 {"Bemba", "bem", ""},
1546 {"Bengali", "ben", "bn", MAKELCID( MAKELANGID(LANG_BENGALI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1547 {"Berber (Other)", "ber", ""},
1548 {"Bhojpuri", "bho", ""},
1549 {"Bihari", "bih", "bh"},
1550 {"Bikol", "bik", ""},
1551 {"Bini", "bin", ""},
1552 {"Bislama", "bis", "bi"},
1553 {"Bokmål, Norwegian; Norwegian Bokmål", "nob", "nb"},
1554 {"Bosnian", "bos", "bs"},
1555 {"Braj", "bra", ""},
1556 {"Breton", "bre", "br", MAKELCID( MAKELANGID(LANG_BRETON
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1557 {"Buginese", "bug", ""},
1558 {"Bulgarian", "bul", "bg", MAKELCID( MAKELANGID(LANG_BULGARIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1559 {"Buriat", "bua", ""},
1560 {"Burmese", "bur", "my"},
1561 {"Burmese", "mya", "my"},
1562 {"Caddo", "cad", ""},
1563 {"Carib", "car", ""},
1564 {"Spanish; Castilian", "spa", "es", MAKELCID( MAKELANGID(LANG_SPANISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1565 {"Catalan", "cat", "ca", MAKELCID( MAKELANGID(LANG_CATALAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1566 {"Caucasian (Other)", "cau", ""},
1567 {"Cebuano", "ceb", ""},
1568 {"Celtic (Other)", "cel", ""},
1569 {"Central American Indian (Other)", "cai", ""},
1570 {"Chagatai", "chg", ""},
1571 {"Chamic languages", "cmc", ""},
1572 {"Chamorro", "cha", "ch"},
1573 {"Chechen", "che", "ce"},
1574 {"Cherokee", "chr", ""},
1575 {"Chewa; Chichewa; Nyanja", "nya", "ny"},
1576 {"Cheyenne", "chy", ""},
1577 {"Chibcha", "chb", ""},
1578 {"Chichewa; Chewa; Nyanja", "nya", "ny"},
1579 {"Chinese", "chi", "zh", MAKELCID( MAKELANGID(LANG_CHINESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1580 {"Chinese", "zho", "zh"},
1581 {"Chinook jargon", "chn", ""},
1582 {"Chipewyan", "chp", ""},
1583 {"Choctaw", "cho", ""},
1584 {"Chuang; Zhuang", "zha", "za"},
1585 {"Church Slavic; Old Church Slavonic", "chu", "cu"},
1586 {"Old Church Slavonic; Old Slavonic; ", "chu", "cu"},
1587 {"Church Slavonic; Old Bulgarian; Church Slavic;", "chu", "cu"},
1588 {"Old Slavonic; Church Slavonic; Old Bulgarian;", "chu", "cu"},
1589 {"Church Slavic; Old Church Slavonic", "chu", "cu"},
1590 {"Chuukese", "chk", ""},
1591 {"Chuvash", "chv", "cv"},
1592 {"Coptic", "cop", ""},
1593 {"Cornish", "cor", "kw"},
1594 {"Corsican", "cos", "co", MAKELCID( MAKELANGID(LANG_CORSICAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1595 {"Cree", "cre", "cr"},
1596 {"Creek", "mus", ""},
1597 {"Creoles and pidgins (Other)", "crp", ""},
1598 {"Creoles and pidgins,", "cpe", ""},
1599 // {"English-based (Other)", "", ""},
1600 {"Creoles and pidgins,", "cpf", ""},
1601 // {"French-based (Other)", "", ""},
1602 {"Creoles and pidgins,", "cpp", ""},
1603 // {"Portuguese-based (Other)", "", ""},
1604 {"Croatian", "scr", "hr", MAKELCID( MAKELANGID(LANG_CROATIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1605 {"Croatian", "hrv", "hr", MAKELCID( MAKELANGID(LANG_CROATIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1606 {"Cushitic (Other)", "cus", ""},
1607 {"Czech", "cze", "cs", MAKELCID( MAKELANGID(LANG_CZECH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1608 {"Czech", "ces", "cs", MAKELCID( MAKELANGID(LANG_CZECH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1609 {"Dakota", "dak", ""},
1610 {"Danish", "dan", "da", MAKELCID( MAKELANGID(LANG_DANISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1611 {"Dargwa", "dar", ""},
1612 {"Dayak", "day", ""},
1613 {"Delaware", "del", ""},
1614 {"Dinka", "din", ""},
1615 {"Divehi", "div", "dv", MAKELCID( MAKELANGID(LANG_DIVEHI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1616 {"Dogri", "doi", ""},
1617 {"Dogrib", "dgr", ""},
1618 {"Dravidian (Other)", "dra", ""},
1619 {"Duala", "dua", ""},
1620 {"Dutch; Flemish", "dut", "nl", MAKELCID( MAKELANGID(LANG_DUTCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1621 {"Dutch; Flemish", "nld", "nl", MAKELCID( MAKELANGID(LANG_DUTCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1622 {"Dutch, Middle (ca. 1050-1350)", "dum", ""},
1623 {"Dyula", "dyu", ""},
1624 {"Dzongkha", "dzo", "dz"},
1625 {"Efik", "efi", ""},
1626 {"Egyptian (Ancient)", "egy", ""},
1627 {"Ekajuk", "eka", ""},
1628 {"Elamite", "elx", ""},
1629 {"English", "eng", "en", MAKELCID( MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1630 {"English, Middle (1100-1500)", "enm", ""},
1631 {"English, Old (ca.450-1100)", "ang", ""},
1632 {"Esperanto", "epo", "eo"},
1633 {"Estonian", "est", "et", MAKELCID( MAKELANGID(LANG_ESTONIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1634 {"Ewe", "ewe", "ee"},
1635 {"Ewondo", "ewo", ""},
1636 {"Fang", "fan", ""},
1637 {"Fanti", "fat", ""},
1638 {"Faroese", "fao", "fo", MAKELCID( MAKELANGID(LANG_FAEROESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1639 {"Fijian", "fij", "fj"},
1640 {"Finnish", "fin", "fi", MAKELCID( MAKELANGID(LANG_FINNISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1641 {"Finno-Ugrian (Other)", "fiu", ""},
1642 {"Flemish; Dutch", "dut", "nl"},
1643 {"Flemish; Dutch", "nld", "nl"},
1645 {"French", "fre", "fr", MAKELCID( MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1646 {"French", "fra*", "fr", MAKELCID( MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1647 {"French", "fra", "fr", MAKELCID( MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1648 {"French, Middle (ca.1400-1600)", "frm", ""},
1649 {"French, Old (842-ca.1400)", "fro", ""},
1650 {"Frisian", "fry", "fy", MAKELCID( MAKELANGID(LANG_FRISIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1651 {"Friulian", "fur", ""},
1652 {"Fulah", "ful", "ff"},
1654 {"Gaelic; Scottish Gaelic", "gla", "gd", MAKELCID( MAKELANGID(LANG_GALICIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1655 {"Gallegan", "glg", "gl"},
1656 {"Ganda", "lug", "lg"},
1657 {"Gayo", "gay", ""},
1658 {"Gbaya", "gba", ""},
1659 {"Geez", "gez", ""},
1660 {"Georgian", "geo", "ka", MAKELCID( MAKELANGID(LANG_GEORGIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1661 {"Georgian", "kat", "ka", MAKELCID( MAKELANGID(LANG_GEORGIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1662 {"German", "ger", "de", MAKELCID( MAKELANGID(LANG_GERMAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1663 {"German", "deu", "de", MAKELCID( MAKELANGID(LANG_GERMAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1664 {"German, Low; Saxon, Low; Low German; Low Saxon", "nds", ""},
1665 {"German, Middle High (ca.1050-1500)", "gmh", ""},
1666 {"German, Old High (ca.750-1050)", "goh", ""},
1667 {"Germanic (Other)", "gem", ""},
1668 {"Gikuyu; Kikuyu", "kik", "ki"},
1669 {"Gilbertese", "gil", ""},
1670 {"Gondi", "gon", ""},
1671 {"Gorontalo", "gor", ""},
1672 {"Gothic", "got", ""},
1673 {"Grebo", "grb", ""},
1674 {"Greek, Ancient (to 1453)", "grc", "", MAKELCID( MAKELANGID(LANG_GREEK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1675 {"Greek, Modern (1453-)", "gre", "el", MAKELCID( MAKELANGID(LANG_GREEK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1676 {"Greek, Modern (1453-)", "ell", "el", MAKELCID( MAKELANGID(LANG_GREEK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1677 {"Greenlandic; Kalaallisut", "kal", "kl", MAKELCID( MAKELANGID(LANG_GREENLANDIC
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1678 {"Guarani", "grn", "gn"},
1679 {"Gujarati", "guj", "gu", MAKELCID( MAKELANGID(LANG_GUJARATI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1680 {"Gwich´in", "gwi", ""},
1681 {"Haida", "hai", ""},
1682 {"Hausa", "hau", "ha", MAKELCID( MAKELANGID(LANG_HAUSA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1683 {"Hawaiian", "haw", ""},
1684 {"Hebrew", "heb", "he", MAKELCID( MAKELANGID(LANG_HEBREW
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1685 {"Herero", "her", "hz"},
1686 {"Hiligaynon", "hil", ""},
1687 {"Himachali", "him", ""},
1688 {"Hindi", "hin", "hi", MAKELCID( MAKELANGID(LANG_HINDI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1689 {"Hiri Motu", "hmo", "ho"},
1690 {"Hittite", "hit", ""},
1691 {"Hmong", "hmn", ""},
1692 {"Hungarian", "hun", "hu", MAKELCID( MAKELANGID(LANG_HUNGARIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1693 {"Hupa", "hup", ""},
1694 {"Iban", "iba", ""},
1695 {"Icelandic", "ice", "is", MAKELCID( MAKELANGID(LANG_ICELANDIC
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1696 {"Icelandic", "isl", "is", MAKELCID( MAKELANGID(LANG_ICELANDIC
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1697 {"Ido", "ido", "io"},
1698 {"Igbo", "ibo", "ig", MAKELCID( MAKELANGID(LANG_IGBO
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1700 {"Iloko", "ilo", ""},
1701 {"Inari Sami", "smn", ""},
1702 {"Indic (Other)", "inc", ""},
1703 {"Indo-European (Other)", "ine", ""},
1704 {"Indonesian", "ind", "id", MAKELCID( MAKELANGID(LANG_INDONESIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1705 {"Ingush", "inh", ""},
1706 {"Interlingua (International", "ina", "ia"},
1707 // {"Auxiliary Language Association)", "", ""},
1708 {"Interlingue", "ile", "ie"},
1709 {"Inuktitut", "iku", "iu", MAKELCID( MAKELANGID(LANG_INUKTITUT
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1710 {"Inupiaq", "ipk", "ik"},
1711 {"Iranian (Other)", "ira", ""},
1712 {"Irish", "gle", "ga", MAKELCID( MAKELANGID(LANG_IRISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1713 {"Irish, Middle (900-1200)", "mga", "", MAKELCID( MAKELANGID(LANG_IRISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1714 {"Irish, Old (to 900)", "sga", "", MAKELCID( MAKELANGID(LANG_IRISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1715 {"Iroquoian languages", "iro", ""},
1716 {"Italian", "ita", "it", MAKELCID( MAKELANGID(LANG_ITALIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1717 {"Japanese", "jpn", "ja", MAKELCID( MAKELANGID(LANG_JAPANESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1718 {"Javanese", "jav", "jv"},
1719 {"Judeo-Arabic", "jrb", ""},
1720 {"Judeo-Persian", "jpr", ""},
1721 {"Kabardian", "kbd", ""},
1722 {"Kabyle", "kab", ""},
1723 {"Kachin", "kac", ""},
1724 {"Kalaallisut; Greenlandic", "kal", "kl"},
1725 {"Kamba", "kam", ""},
1726 {"Kannada", "kan", "kn", MAKELCID( MAKELANGID(LANG_KANNADA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1727 {"Kanuri", "kau", "kr"},
1728 {"Kara-Kalpak", "kaa", ""},
1729 {"Karen", "kar", ""},
1730 {"Kashmiri", "kas", "ks", MAKELCID( MAKELANGID(LANG_KASHMIRI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1731 {"Kawi", "kaw", ""},
1732 {"Kazakh", "kaz", "kk", MAKELCID( MAKELANGID(LANG_KAZAK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1733 {"Khasi", "kha", ""},
1734 {"Khmer", "khm", "km", MAKELCID( MAKELANGID(LANG_KHMER
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1735 {"Khoisan (Other)", "khi", ""},
1736 {"Khotanese", "kho", ""},
1737 {"Kikuyu; Gikuyu", "kik", "ki"},
1738 {"Kimbundu", "kmb", ""},
1739 {"Kinyarwanda", "kin", "rw", MAKELCID( MAKELANGID(LANG_KINYARWANDA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1740 {"Kirghiz", "kir", "ky"},
1741 {"Komi", "kom", "kv"},
1742 {"Kongo", "kon", "kg"},
1743 {"Konkani", "kok", "", MAKELCID( MAKELANGID(LANG_KONKANI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1744 {"Korean", "kor", "ko", MAKELCID( MAKELANGID(LANG_KOREAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1745 {"Kosraean", "kos", ""},
1746 {"Kpelle", "kpe", ""},
1748 {"Kuanyama; Kwanyama", "kua", "kj"},
1749 {"Kumyk", "kum", ""},
1750 {"Kurdish", "kur", "ku"},
1751 {"Kurukh", "kru", ""},
1752 {"Kutenai", "kut", ""},
1753 {"Kwanyama, Kuanyama", "kua", "kj"},
1754 {"Ladino", "lad", ""},
1755 {"Lahnda", "lah", ""},
1756 {"Lamba", "lam", ""},
1757 {"Lao", "lao", "lo", MAKELCID( MAKELANGID(LANG_LAO
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1758 {"Latin", "lat", "la"},
1759 {"Latvian", "lav", "lv", MAKELCID( MAKELANGID(LANG_LATVIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1760 {"Letzeburgesch; Luxembourgish", "ltz", "lb"},
1761 {"Lezghian", "lez", ""},
1762 {"Limburgan; Limburger; Limburgish", "lim", "li"},
1763 {"Limburger; Limburgan; Limburgish;", "lim", "li"},
1764 {"Limburgish; Limburger; Limburgan", "lim", "li"},
1765 {"Lingala", "lin", "ln"},
1766 {"Lithuanian", "lit", "lt", MAKELCID( MAKELANGID(LANG_LITHUANIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1767 {"Low German; Low Saxon; German, Low; Saxon, Low", "nds", ""},
1768 {"Low Saxon; Low German; Saxon, Low; German, Low", "nds", ""},
1769 {"Lozi", "loz", ""},
1770 {"Luba-Katanga", "lub", "lu"},
1771 {"Luba-Lulua", "lua", ""},
1772 {"Luiseno", "lui", ""},
1773 {"Lule Sami", "smj", ""},
1774 {"Lunda", "lun", ""},
1775 {"Luo (Kenya and Tanzania)", "luo", ""},
1776 {"Lushai", "lus", ""},
1777 {"Luxembourgish; Letzeburgesch", "ltz", "lb", MAKELCID( MAKELANGID(LANG_LUXEMBOURGISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1778 {"Macedonian", "mac", "mk", MAKELCID( MAKELANGID(LANG_MACEDONIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1779 {"Macedonian", "mkd", "mk", MAKELCID( MAKELANGID(LANG_MACEDONIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1780 {"Madurese", "mad", ""},
1781 {"Magahi", "mag", ""},
1782 {"Maithili", "mai", ""},
1783 {"Makasar", "mak", ""},
1784 {"Malagasy", "mlg", "mg"},
1785 {"Malay", "may", "ms", MAKELCID( MAKELANGID(LANG_MALAY
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1786 {"Malay", "msa", "ms", MAKELCID( MAKELANGID(LANG_MALAY
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1787 {"Malayalam", "mal", "ml", MAKELCID( MAKELANGID(LANG_MALAYALAM
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1788 {"Maltese", "mlt", "mt", MAKELCID( MAKELANGID(LANG_MALTESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1789 {"Manchu", "mnc", ""},
1790 {"Mandar", "mdr", ""},
1791 {"Mandingo", "man", ""},
1792 {"Manipuri", "mni", "", MAKELCID( MAKELANGID(LANG_MANIPURI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1793 {"Manobo languages", "mno", ""},
1794 {"Manx", "glv", "gv"},
1795 {"Maori", "mao", "mi", MAKELCID( MAKELANGID(LANG_MAORI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1796 {"Maori", "mri", "mi", MAKELCID( MAKELANGID(LANG_MAORI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1797 {"Marathi", "mar", "mr", MAKELCID( MAKELANGID(LANG_MARATHI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1798 {"Mari", "chm", ""},
1799 {"Marshallese", "mah", "mh"},
1800 {"Marwari", "mwr", ""},
1801 {"Masai", "mas", ""},
1802 {"Mayan languages", "myn", ""},
1803 {"Mende", "men", ""},
1804 {"Micmac", "mic", ""},
1805 {"Minangkabau", "min", ""},
1806 {"Miscellaneous languages", "mis", ""},
1807 {"Mohawk", "moh", "", MAKELCID( MAKELANGID(LANG_MOHAWK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1808 {"Moldavian", "mol", "mo"},
1809 {"Mon-Khmer (Other)", "mkh", ""},
1810 {"Mongo", "lol", ""},
1811 {"Mongolian", "mon", "mn", MAKELCID( MAKELANGID(LANG_MONGOLIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1812 {"Mossi", "mos", ""},
1813 {"Multiple languages", "mul", ""},
1814 {"Munda languages", "mun", ""},
1815 {"Nahuatl", "nah", ""},
1816 {"Nauru", "nau", "na"},
1817 {"Navaho, Navajo", "nav", "nv"},
1818 {"Navajo; Navaho", "nav", "nv"},
1819 {"Ndebele, North", "nde", "nd"},
1820 {"Ndebele, South", "nbl", "nr"},
1821 {"Ndonga", "ndo", "ng"},
1822 {"Neapolitan", "nap", ""},
1823 {"Nepali", "nep", "ne", MAKELCID( MAKELANGID(LANG_NEPALI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1824 {"Newari", "new", ""},
1825 {"Nias", "nia", ""},
1826 {"Niger-Kordofanian (Other)", "nic", ""},
1827 {"Nilo-Saharan (Other)", "ssa", ""},
1828 {"Niuean", "niu", ""},
1829 {"Norse, Old", "non", ""},
1830 {"North American Indian (Other)", "nai", ""},
1831 {"Northern Sami", "sme", "se"},
1832 {"North Ndebele", "nde", "nd"},
1833 {"Norwegian", "nor", "no", MAKELCID( MAKELANGID(LANG_NORWEGIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1834 {"Norwegian Bokmål; Bokmål, Norwegian", "nob", "nb", MAKELCID( MAKELANGID(LANG_NORWEGIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1835 {"Norwegian Nynorsk; Nynorsk, Norwegian", "nno", "nn", MAKELCID( MAKELANGID(LANG_NORWEGIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1836 {"Nubian languages", "nub", ""},
1837 {"Nyamwezi", "nym", ""},
1838 {"Nyanja; Chichewa; Chewa", "nya", "ny"},
1839 {"Nyankole", "nyn", ""},
1840 {"Nynorsk, Norwegian; Norwegian Nynorsk", "nno", "nn"},
1841 {"Nyoro", "nyo", ""},
1842 {"Nzima", "nzi", ""},
1843 {"Occitan (post 1500},; Provençal", "oci", "oc", MAKELCID( MAKELANGID(LANG_OCCITAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1844 {"Ojibwa", "oji", "oj"},
1845 {"Old Bulgarian; Old Slavonic; Church Slavonic;", "chu", "cu"},
1846 {"Oriya", "ori", "or"},
1847 {"Oromo", "orm", "om"},
1848 {"Osage", "osa", ""},
1849 {"Ossetian; Ossetic", "oss", "os"},
1850 {"Ossetic; Ossetian", "oss", "os"},
1851 {"Otomian languages", "oto", ""},
1852 {"Pahlavi", "pal", ""},
1853 {"Palauan", "pau", ""},
1854 {"Pali", "pli", "pi"},
1855 {"Pampanga", "pam", ""},
1856 {"Pangasinan", "pag", ""},
1857 {"Panjabi", "pan", "pa"},
1858 {"Papiamento", "pap", ""},
1859 {"Papuan (Other)", "paa", ""},
1860 {"Persian", "per", "fa", MAKELCID( MAKELANGID(LANG_PERSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1861 {"Persian", "fas", "fa", MAKELCID( MAKELANGID(LANG_PERSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1862 {"Persian, Old (ca.600-400 B.C.)", "peo", ""},
1863 {"Philippine (Other)", "phi", ""},
1864 {"Phoenician", "phn", ""},
1865 {"Pohnpeian", "pon", ""},
1866 {"Polish", "pol", "pl", MAKELCID( MAKELANGID(LANG_POLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1867 {"Portuguese", "por", "pt", MAKELCID( MAKELANGID(LANG_PORTUGUESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1868 {"Prakrit languages", "pra", ""},
1869 {"Provençal; Occitan (post 1500)", "oci", "oc"},
1870 {"Provençal, Old (to 1500)", "pro", ""},
1871 {"Pushto", "pus", "ps"},
1872 {"Quechua", "que", "qu", MAKELCID( MAKELANGID(LANG_QUECHUA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1873 {"Raeto-Romance", "roh", "rm"},
1874 {"Rajasthani", "raj", ""},
1875 {"Rapanui", "rap", ""},
1876 {"Rarotongan", "rar", ""},
1877 {"Reserved for local use", "qaa-qtz", ""},
1878 {"Romance (Other)", "roa", ""},
1879 {"Romanian", "rum", "ro", MAKELCID( MAKELANGID(LANG_ROMANIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1880 {"Romanian", "ron", "ro", MAKELCID( MAKELANGID(LANG_ROMANIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1881 {"Romany", "rom", ""},
1882 {"Rundi", "run", "rn"},
1883 {"Russian", "rus", "ru", MAKELCID( MAKELANGID(LANG_RUSSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1884 {"Salishan languages", "sal", ""},
1885 {"Samaritan Aramaic", "sam", ""},
1886 {"Sami languages (Other)", "smi", ""},
1887 {"Samoan", "smo", "sm"},
1888 {"Sandawe", "sad", ""},
1889 {"Sango", "sag", "sg"},
1890 {"Sanskrit", "san", "sa", MAKELCID( MAKELANGID(LANG_SANSKRIT
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1891 {"Santali", "sat", ""},
1892 {"Sardinian", "srd", "sc"},
1893 {"Sasak", "sas", ""},
1894 {"Saxon, Low; German, Low; Low Saxon; Low German", "nds", ""},
1895 {"Scots", "sco", ""},
1896 {"Scottish Gaelic; Gaelic", "gla", "gd"},
1897 {"Selkup", "sel", ""},
1898 {"Semitic (Other)", "sem", ""},
1899 {"Serbian", "scc", "sr", MAKELCID( MAKELANGID(LANG_SERBIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1900 {"Serbian", "srp", "sr", MAKELCID( MAKELANGID(LANG_SERBIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1901 {"Serer", "srr", ""},
1902 {"Shan", "shn", ""},
1903 {"Shona", "sna", "sn"},
1904 {"Sichuan Yi", "iii", "ii"},
1905 {"Sidamo", "sid", ""},
1906 {"Sign languages", "sgn", ""},
1907 {"Siksika", "bla", ""},
1908 {"Sindhi", "snd", "sd", MAKELCID( MAKELANGID(LANG_SINDHI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1909 {"Sinhalese", "sin", "si", MAKELCID( MAKELANGID(LANG_SINHALESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1910 {"Sino-Tibetan (Other)", "sit", ""},
1911 {"Siouan languages", "sio", ""},
1912 {"Skolt Sami", "sms", ""},
1913 {"Slave (Athapascan)", "den", ""},
1914 {"Slavic (Other)", "sla", ""},
1915 {"Slovak", "slo", "sk", MAKELCID( MAKELANGID(LANG_SLOVAK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1916 {"Slovak", "slk", "sk", MAKELCID( MAKELANGID(LANG_SLOVAK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1917 {"Slovenian", "slv", "sl", MAKELCID( MAKELANGID(LANG_SLOVENIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1918 {"Sogdian", "sog", ""},
1919 {"Somali", "som", "so"},
1920 {"Songhai", "son", ""},
1921 {"Soninke", "snk", ""},
1922 {"Sorbian languages", "wen", ""},
1923 {"Sotho, Northern", "nso", "", MAKELCID( MAKELANGID(LANG_SOTHO
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1924 {"Sotho, Southern", "sot", "st", MAKELCID( MAKELANGID(LANG_SOTHO
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1925 {"South American Indian (Other)", "sai", ""},
1926 {"Southern Sami", "sma", ""},
1927 {"South Ndebele", "nbl", "nr"},
1928 {"Spanish; Castilian", "spa", "es", MAKELCID( MAKELANGID(LANG_SPANISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1929 {"Sukuma", "suk", ""},
1930 {"Sumerian", "sux", ""},
1931 {"Sundanese", "sun", "su"},
1932 {"Susu", "sus", ""},
1933 {"Swahili", "swa", "sw", MAKELCID( MAKELANGID(LANG_SWAHILI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1934 {"Swati", "ssw", "ss"},
1935 {"Swedish", "swe", "sv", MAKELCID( MAKELANGID(LANG_SWEDISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1936 {"Syriac", "syr", "", MAKELCID( MAKELANGID(LANG_SYRIAC
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1937 {"Tagalog", "tgl", "tl"},
1938 {"Tahitian", "tah", "ty"},
1939 {"Tai (Other)", "tai", ""},
1940 {"Tajik", "tgk", "tg", MAKELCID( MAKELANGID(LANG_TAJIK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1941 {"Tamashek", "tmh", ""},
1942 {"Tamil", "tam", "ta", MAKELCID( MAKELANGID(LANG_TAMIL
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1943 {"Tatar", "tat", "tt", MAKELCID( MAKELANGID(LANG_TATAR
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1944 {"Telugu", "tel", "te", MAKELCID( MAKELANGID(LANG_TELUGU
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1945 {"Tereno", "ter", ""},
1946 {"Tetum", "tet", ""},
1947 {"Thai", "tha", "th", MAKELCID( MAKELANGID(LANG_THAI
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1948 {"Tibetan", "tib", "bo", MAKELCID( MAKELANGID(LANG_TIBETAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1949 {"Tibetan", "bod", "bo", MAKELCID( MAKELANGID(LANG_TIBETAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1950 {"Tigre", "tig", ""},
1951 {"Tigrinya", "tir", "ti", MAKELCID( MAKELANGID(LANG_TIGRIGNA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1952 {"Timne", "tem", ""},
1954 {"Tlingit", "tli", ""},
1955 {"Tok Pisin", "tpi", ""},
1956 {"Tokelau", "tkl", ""},
1957 {"Tonga (Nyasa)", "tog", ""},
1958 {"Tonga (Tonga Islands)", "ton", "to"},
1959 {"Tsimshian", "tsi", ""},
1960 {"Tsonga", "tso", "ts"},
1961 {"Tswana", "tsn", "tn", MAKELCID( MAKELANGID(LANG_TSWANA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1962 {"Tumbuka", "tum", ""},
1963 {"Tupi languages", "tup", ""},
1964 {"Turkish", "tur", "tr", MAKELCID( MAKELANGID(LANG_TURKISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1965 {"Turkish, Ottoman (1500-1928)", "ota", "", MAKELCID( MAKELANGID(LANG_TURKISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1966 {"Turkmen", "tuk", "tk", MAKELCID( MAKELANGID(LANG_TURKMEN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1967 {"Tuvalu", "tvl", ""},
1968 {"Tuvinian", "tyv", ""},
1969 {"Twi", "twi", "tw"},
1970 {"Ugaritic", "uga", ""},
1971 {"Uighur", "uig", "ug", MAKELCID( MAKELANGID(LANG_UIGHUR
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1972 {"Ukrainian", "ukr", "uk", MAKELCID( MAKELANGID(LANG_UKRAINIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1973 {"Umbundu", "umb", ""},
1974 {"Undetermined", "und", ""},
1975 {"Urdu", "urd", "ur", MAKELCID( MAKELANGID(LANG_URDU
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1976 {"Uzbek", "uzb", "uz", MAKELCID( MAKELANGID(LANG_UZBEK
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1978 {"Venda", "ven", "ve"},
1979 {"Vietnamese", "vie", "vi", MAKELCID( MAKELANGID(LANG_VIETNAMESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1980 {"Volapuk", "vol", "vo"},
1981 {"Votic", "vot", ""},
1982 {"Wakashan languages", "wak", ""},
1983 {"Walamo", "wal", ""},
1984 {"Walloon", "wln", "wa"},
1985 {"Waray", "war", ""},
1986 {"Washo", "was", ""},
1987 {"Welsh", "wel", "cy", MAKELCID( MAKELANGID(LANG_WELSH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1988 {"Welsh", "cym", "cy", MAKELCID( MAKELANGID(LANG_WELSH
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1989 {"Wolof", "wol", "wo", MAKELCID( MAKELANGID(LANG_WOLOF
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1990 {"Xhosa", "xho", "xh", MAKELCID( MAKELANGID(LANG_XHOSA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1991 {"Yakut", "sah", "", MAKELCID( MAKELANGID(LANG_YAKUT
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1993 {"Yapese", "yap", ""},
1994 {"Yiddish", "yid", "yi"},
1995 {"Yoruba", "yor", "yo", MAKELCID( MAKELANGID(LANG_YORUBA
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
1996 {"Yupik languages", "ypk", ""},
1997 {"Zande", "znd", ""},
1998 {"Zapotec", "zap", ""},
1999 {"Zenaga", "zen", ""},
2000 {"Zhuang; Chuang", "zha", "za"},
2001 {"Zulu", "zul", "zu", MAKELCID( MAKELANGID(LANG_ZULU
, SUBLANG_DEFAULT
), SORT_DEFAULT
)},
2002 {"Zuni", "zun", ""},
2003 {"Classical Newari", "nwc", ""},
2004 {"Klingon", "tlh", ""},
2005 {"Blin", "byn", ""},
2006 {"Lojban", "jbo", ""},
2007 {"Lower Sorbian", "dsb", ""},
2008 {"Upper Sorbian", "hsb", ""},
2009 {"Kashubian", "csb", ""},
2010 {"Crimean Turkish", "crh", ""},
2011 {"Erzya", "myv", ""},
2012 {"Moksha", "mdf", ""},
2013 {"Karachay-Balkar", "krc", ""},
2014 {"Adyghe", "ady", ""},
2015 {"Udmurt", "udm", ""},
2016 {"Dargwa", "dar", ""},
2017 {"Ingush", "inh", ""},
2018 {"Nogai", "nog", ""},
2019 {"Haitian", "hat", "ht"},
2020 {"Kalmyk", "xal", ""},
2022 {"No subtitles", "---", "", (LCID
)LCID_NOSUBTITLES
},
2025 CString
ISO6391ToLanguage(LPCSTR code
)
2028 strncpy(tmp
, code
, 2);
2031 for(int i
= 0, j
= countof(s_isolangs
); i
< j
; i
++)
2032 if(!strcmp(s_isolangs
[i
].iso6391
, tmp
))
2034 CString ret
= CString(CStringA(s_isolangs
[i
].name
));
2035 int i
= ret
.Find(';');
2036 if(i
> 0) ret
= ret
.Left(i
);
2042 CString
ISO6392ToLanguage(LPCSTR code
)
2045 strncpy(tmp
, code
, 3);
2048 for(int i
= 0, j
= countof(s_isolangs
); i
< j
; i
++)
2050 if(!strcmp(s_isolangs
[i
].iso6392
, tmp
))
2052 CString ret
= CString(CStringA(s_isolangs
[i
].name
));
2053 int i
= ret
.Find(';');
2054 if(i
> 0) ret
= ret
.Left(i
);
2058 return CString(code
);
2061 LCID
ISO6391ToLcid(LPCSTR code
)
2064 strncpy_s(tmp
, code
, 3);
2067 for(ptrdiff_t i
= 0, j
= countof(s_isolangs
); i
< j
; i
++) {
2068 if(!strcmp(s_isolangs
[i
].iso6391
, code
)) {
2069 return s_isolangs
[i
].lcid
;
2075 LCID
ISO6392ToLcid(LPCSTR code
)
2078 strncpy_s(tmp
, code
, 3);
2081 for(ptrdiff_t i
= 0, j
= countof(s_isolangs
); i
< j
; i
++) {
2082 if(!strcmp(s_isolangs
[i
].iso6392
, tmp
)) {
2083 return s_isolangs
[i
].lcid
;
2089 CString
ISO6391To6392(LPCSTR code
)
2092 strncpy(tmp
, code
, 2);
2095 for(int i
= 0, j
= countof(s_isolangs
); i
< j
; i
++)
2096 if(!strcmp(s_isolangs
[i
].iso6391
, tmp
))
2097 return CString(CStringA(s_isolangs
[i
].iso6392
));
2101 CString
ISO6392To6391(LPCSTR code
)
2104 strncpy(tmp
, code
, 3);
2107 for(int i
= 0, j
= countof(s_isolangs
); i
< j
; i
++)
2108 if(!strcmp(s_isolangs
[i
].iso6392
, tmp
))
2109 return CString(CStringA(s_isolangs
[i
].iso6391
));
2113 CString
LanguageToISO6392(LPCTSTR lang
)
2117 for(int i
= 0, j
= countof(s_isolangs
); i
< j
; i
++)
2119 CAtlList
<CString
> sl
;
2120 Explode(CString(s_isolangs
[i
].name
), sl
, ';');
2121 POSITION pos
= sl
.GetHeadPosition();
2124 if(!str
.CompareNoCase(sl
.GetNext(pos
)))
2125 return CString(s_isolangs
[i
].iso6392
);
2131 int MakeAACInitData(BYTE
* pData
, int profile
, int freq
, int channels
)
2135 if(92017 <= freq
) srate_idx
= 0;
2136 else if(75132 <= freq
) srate_idx
= 1;
2137 else if(55426 <= freq
) srate_idx
= 2;
2138 else if(46009 <= freq
) srate_idx
= 3;
2139 else if(37566 <= freq
) srate_idx
= 4;
2140 else if(27713 <= freq
) srate_idx
= 5;
2141 else if(23004 <= freq
) srate_idx
= 6;
2142 else if(18783 <= freq
) srate_idx
= 7;
2143 else if(13856 <= freq
) srate_idx
= 8;
2144 else if(11502 <= freq
) srate_idx
= 9;
2145 else if(9391 <= freq
) srate_idx
= 10;
2146 else srate_idx
= 11;
2148 pData
[0] = ((abs(profile
) + 1) << 3) | ((srate_idx
& 0xe) >> 1);
2149 pData
[1] = ((srate_idx
& 0x1) << 7) | (channels
<< 3);
2157 if(92017 <= freq
) srate_idx
= 0;
2158 else if(75132 <= freq
) srate_idx
= 1;
2159 else if(55426 <= freq
) srate_idx
= 2;
2160 else if(46009 <= freq
) srate_idx
= 3;
2161 else if(37566 <= freq
) srate_idx
= 4;
2162 else if(27713 <= freq
) srate_idx
= 5;
2163 else if(23004 <= freq
) srate_idx
= 6;
2164 else if(18783 <= freq
) srate_idx
= 7;
2165 else if(13856 <= freq
) srate_idx
= 8;
2166 else if(11502 <= freq
) srate_idx
= 9;
2167 else if(9391 <= freq
) srate_idx
= 10;
2168 else srate_idx
= 11;
2170 pData
[2] = 0x2B7>>3;
2171 pData
[3] = (BYTE
)((0x2B7<<5) | 5);
2172 pData
[4] = (1<<7) | (srate_idx
<<3);
2180 BOOL
CFileGetStatus(LPCTSTR lpszFileName
, CFileStatus
& status
)
2184 return CFile::GetStatus(lpszFileName
, status
);
2186 catch(CException
* e
)
2188 // MFCBUG: E_INVALIDARG / "Parameter is incorrect" is thrown for certain cds (vs2003)
2189 // http://groups.google.co.uk/groups?hl=en&lr=&ie=UTF-8&threadm=OZuXYRzWDHA.536%40TK2MSFTNGP10.phx.gbl&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1
2190 TRACE(_T("CFile::GetStatus has thrown an exception\n"));
2196 // filter registration helpers
2198 bool DeleteRegKey(LPCTSTR pszKey
, LPCTSTR pszSubkey
)
2203 LONG ec
= ::RegOpenKeyEx(HKEY_CLASSES_ROOT
, pszKey
, 0, KEY_ALL_ACCESS
, &hKey
);
2204 if(ec
== ERROR_SUCCESS
)
2207 ec
= ::RegDeleteKey(hKey
, pszSubkey
);
2209 bOK
= (ec
== ERROR_SUCCESS
);
2211 ::RegCloseKey(hKey
);
2217 bool SetRegKeyValue(LPCTSTR pszKey
, LPCTSTR pszSubkey
, LPCTSTR pszValueName
, LPCTSTR pszValue
)
2221 CString
szKey(pszKey
);
2223 szKey
+= CString(_T("\\")) + pszSubkey
;
2226 LONG ec
= ::RegCreateKeyEx(HKEY_CLASSES_ROOT
, szKey
, 0, 0, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, 0, &hKey
, 0);
2227 if(ec
== ERROR_SUCCESS
)
2231 ec
= ::RegSetValueEx(hKey
, pszValueName
, 0, REG_SZ
,
2232 reinterpret_cast<BYTE
*>(const_cast<LPTSTR
>(pszValue
)),
2233 (_tcslen(pszValue
) + 1) * sizeof(TCHAR
));
2236 bOK
= (ec
== ERROR_SUCCESS
);
2238 ::RegCloseKey(hKey
);
2244 bool SetRegKeyValue(LPCTSTR pszKey
, LPCTSTR pszSubkey
, LPCTSTR pszValue
)
2246 return SetRegKeyValue(pszKey
, pszSubkey
, 0, pszValue
);
2249 void RegisterSourceFilter(const CLSID
& clsid
, const GUID
& subtype2
, LPCTSTR chkbytes
, LPCTSTR ext
, ...)
2251 CString null
= CStringFromGUID(GUID_NULL
);
2252 CString majortype
= CStringFromGUID(MEDIATYPE_Stream
);
2253 CString subtype
= CStringFromGUID(subtype2
);
2255 SetRegKeyValue(_T("Media Type\\") + majortype
, subtype
, _T("0"), chkbytes
);
2256 SetRegKeyValue(_T("Media Type\\") + majortype
, subtype
, _T("Source Filter"), CStringFromGUID(clsid
));
2258 DeleteRegKey(_T("Media Type\\") + null
, subtype
);
2261 va_start(marker
, ext
);
2262 for(; ext
; ext
= va_arg(marker
, LPCTSTR
))
2263 DeleteRegKey(_T("Media Type\\Extensions"), ext
);
2267 void RegisterSourceFilter(const CLSID
& clsid
, const GUID
& subtype2
, const CAtlList
<CString
>& chkbytes
, LPCTSTR ext
, ...)
2269 CString null
= CStringFromGUID(GUID_NULL
);
2270 CString majortype
= CStringFromGUID(MEDIATYPE_Stream
);
2271 CString subtype
= CStringFromGUID(subtype2
);
2273 POSITION pos
= chkbytes
.GetHeadPosition();
2274 for(int i
= 0; pos
; i
++)
2277 idx
.Format(_T("%d"), i
);
2278 SetRegKeyValue(_T("Media Type\\") + majortype
, subtype
, idx
, chkbytes
.GetNext(pos
));
2281 SetRegKeyValue(_T("Media Type\\") + majortype
, subtype
, _T("Source Filter"), CStringFromGUID(clsid
));
2283 DeleteRegKey(_T("Media Type\\") + null
, subtype
);
2286 va_start(marker
, ext
);
2287 for(; ext
; ext
= va_arg(marker
, LPCTSTR
))
2288 DeleteRegKey(_T("Media Type\\Extensions"), ext
);
2292 void UnRegisterSourceFilter(const GUID
& subtype
)
2294 DeleteRegKey(_T("Media Type\\") + CStringFromGUID(MEDIATYPE_Stream
), CStringFromGUID(subtype
));
2297 // hour, minute, second, millisec
2298 CString
ReftimeToString(const REFERENCE_TIME
& rtVal
)
2301 LONGLONG llTotalMs
= ConvertToMilliseconds (rtVal
);
2302 int lHour
= (int)(llTotalMs
/ (1000*60*60));
2303 int lMinute
= (llTotalMs
/ (1000*60)) % 60;
2304 int lSecond
= (llTotalMs
/ 1000) % 60;
2305 int lMillisec
= llTotalMs
% 1000;
2306 strTemp
.Format (_T("%02d:%02d:%02d,%03d"), lHour
, lMinute
, lSecond
, lMillisec
);
2310 // hour, minute, second (round)
2311 CString
ReftimeToString2(const REFERENCE_TIME
& rtVal
)
2314 LONGLONG seconds
= (rtVal
+ 5000000) / 10000000;
2315 int lHour
= (int)(seconds
/ 3600);
2316 int lMinute
= (int)(seconds
/ 60 % 60);
2317 int lSecond
= (int)(seconds
% 60);
2319 strTemp
.Format (_T("%02d:%02d:%02d"), lHour
, lMinute
, lSecond
);
2323 CString
DVDtimeToString(const DVD_HMSF_TIMECODE
& rtVal
, bool bAlwaysShowHours
)
2326 if (rtVal
.bHours
> 0 || bAlwaysShowHours
) {
2327 strTemp
.Format(_T("%02d:%02d:%02d"), rtVal
.bHours
, rtVal
.bMinutes
, rtVal
.bSeconds
);
2329 strTemp
.Format(_T("%02d:%02d"), rtVal
.bMinutes
, rtVal
.bSeconds
);
2334 REFERENCE_TIME
StringToReftime(LPCTSTR strVal
)
2336 REFERENCE_TIME rt
= 0;
2342 if (_stscanf_s (strVal
, _T("%02d:%02d:%02d,%03d"), &lHour
, &lMinute
, &lSecond
, &lMillisec
) == 4) {
2343 rt
= ( (((lHour
*24)+lMinute
)*60 + lSecond
) * MILLISECONDS
+ lMillisec
) * (UNITS
/MILLISECONDS
);
2349 const double Rec601_Kr
= 0.299;
2350 const double Rec601_Kb
= 0.114;
2351 const double Rec601_Kg
= 0.587;
2352 COLORREF
YCrCbToRGB_Rec601(BYTE Y
, BYTE Cr
, BYTE Cb
)
2355 double rp
= Y
+ 2*(Cr
-128)*(1.0-Rec601_Kr
);
2356 double gp
= Y
- 2*(Cb
-128)*(1.0-Rec601_Kb
)*Rec601_Kb
/Rec601_Kg
- 2*(Cr
-128)*(1.0-Rec601_Kr
)*Rec601_Kr
/Rec601_Kg
;
2357 double bp
= Y
+ 2*(Cb
-128)*(1.0-Rec601_Kb
);
2359 return RGB (fabs(rp
), fabs(gp
), fabs(bp
));
2362 DWORD
YCrCbToRGB_Rec601(BYTE A
, BYTE Y
, BYTE Cr
, BYTE Cb
)
2365 double rp
= Y
+ 2*(Cr
-128)*(1.0-Rec601_Kr
);
2366 double gp
= Y
- 2*(Cb
-128)*(1.0-Rec601_Kb
)*Rec601_Kb
/Rec601_Kg
- 2*(Cr
-128)*(1.0-Rec601_Kr
)*Rec601_Kr
/Rec601_Kg
;
2367 double bp
= Y
+ 2*(Cb
-128)*(1.0-Rec601_Kb
);
2369 return D3DCOLOR_ARGB(A
, (BYTE
)fabs(rp
), (BYTE
)fabs(gp
), (BYTE
)fabs(bp
));
2373 const double Rec709_Kr
= 0.2125;
2374 const double Rec709_Kb
= 0.0721;
2375 const double Rec709_Kg
= 0.7154;
2377 COLORREF
YCrCbToRGB_Rec709(BYTE Y
, BYTE Cr
, BYTE Cb
)
2380 double rp
= Y
+ 2*(Cr
-128)*(1.0-Rec709_Kr
);
2381 double gp
= Y
- 2*(Cb
-128)*(1.0-Rec709_Kb
)*Rec709_Kb
/Rec709_Kg
- 2*(Cr
-128)*(1.0-Rec709_Kr
)*Rec709_Kr
/Rec709_Kg
;
2382 double bp
= Y
+ 2*(Cb
-128)*(1.0-Rec709_Kb
);
2384 return RGB (fabs(rp
), fabs(gp
), fabs(bp
));
2387 DWORD
YCrCbToRGB_Rec709(BYTE A
, BYTE Y
, BYTE Cr
, BYTE Cb
)
2390 double rp
= Y
+ 2*(Cr
-128)*(1.0-Rec709_Kr
);
2391 double gp
= Y
- 2*(Cb
-128)*(1.0-Rec709_Kb
)*Rec709_Kb
/Rec709_Kg
- 2*(Cr
-128)*(1.0-Rec709_Kr
)*Rec709_Kr
/Rec709_Kg
;
2392 double bp
= Y
+ 2*(Cb
-128)*(1.0-Rec709_Kb
);
2394 return D3DCOLOR_ARGB (A
, (BYTE
)fabs(rp
), (BYTE
)fabs(gp
), (BYTE
)fabs(bp
));