293 lines
14 KiB
C++
293 lines
14 KiB
C++
#ifndef __MEDIAPROP_H__
|
|
#define __MEDIAPROP_H__
|
|
|
|
// These should be moved into some central location
|
|
#define PIDISI_CX 0x00000003L // VT_UI4
|
|
#define PIDISI_CY 0x00000004L // VT_UI4
|
|
#define PIDISI_FRAME_COUNT 0x0000000CL // VT_LPWSTR
|
|
#define PIDISI_DIMENSIONS 0x0000000DL // VT_LPWSTR
|
|
|
|
|
|
#define IsEqualSCID(a, b) (((a).pid == (b).pid) && IsEqualIID((a).fmtid, (b).fmtid) )
|
|
|
|
typedef struct
|
|
{
|
|
const SHCOLUMNID *pscid;
|
|
LPCWSTR pszName; // Propstg string name for this property.
|
|
VARTYPE vt; // Note that the type of a given FMTID/PID pair is a known, fixed value
|
|
BOOL bEnumerate; // We don't want to enumerate alias properties.
|
|
} COLMAP;
|
|
|
|
|
|
#define DEFINE_SCID(name, fmtid, pid) const SHCOLUMNID name = { fmtid, pid }
|
|
|
|
DEFINE_SCID(SCID_Author, PSGUID_SUMMARYINFORMATION, PIDSI_AUTHOR);
|
|
DEFINE_SCID(SCID_Title, PSGUID_SUMMARYINFORMATION, PIDSI_TITLE);
|
|
DEFINE_SCID(SCID_Comment, PSGUID_SUMMARYINFORMATION, PIDSI_COMMENTS);
|
|
|
|
DEFINE_SCID(SCID_Category, PSGUID_DOCUMENTSUMMARYINFORMATION, PIDDSI_CATEGORY);
|
|
|
|
DEFINE_SCID(SCID_MUSIC_Artist, PSGUID_MUSIC, PIDSI_ARTIST);
|
|
DEFINE_SCID(SCID_MUSIC_Album, PSGUID_MUSIC, PIDSI_ALBUM);
|
|
DEFINE_SCID(SCID_MUSIC_Year, PSGUID_MUSIC, PIDSI_YEAR);
|
|
DEFINE_SCID(SCID_MUSIC_Track, PSGUID_MUSIC, PIDSI_TRACK);
|
|
DEFINE_SCID(SCID_MUSIC_Genre, PSGUID_MUSIC, PIDSI_GENRE);
|
|
DEFINE_SCID(SCID_MUSIC_Lyrics, PSGUID_MUSIC, PIDSI_LYRICS);
|
|
|
|
DEFINE_SCID(SCID_DRM_Protected, PSGUID_DRM, PIDDRSI_PROTECTED);
|
|
DEFINE_SCID(SCID_DRM_Description, PSGUID_DRM, PIDDRSI_DESCRIPTION);
|
|
DEFINE_SCID(SCID_DRM_PlayCount, PSGUID_DRM, PIDDRSI_PLAYCOUNT);
|
|
DEFINE_SCID(SCID_DRM_PlayStarts, PSGUID_DRM, PIDDRSI_PLAYSTARTS);
|
|
DEFINE_SCID(SCID_DRM_PlayExpires, PSGUID_DRM, PIDDRSI_PLAYEXPIRES);
|
|
|
|
DEFINE_SCID(SCID_VIDEO_StreamName, PSGUID_VIDEO, PIDVSI_STREAM_NAME);
|
|
DEFINE_SCID(SCID_VIDEO_FrameRate, PSGUID_VIDEO, PIDVSI_FRAME_RATE);
|
|
DEFINE_SCID(SCID_VIDEO_Bitrate, PSGUID_VIDEO, PIDVSI_DATA_RATE);
|
|
DEFINE_SCID(SCID_VIDEO_SampleSize, PSGUID_VIDEO, PIDVSI_SAMPLE_SIZE);
|
|
DEFINE_SCID(SCID_VIDEO_Compression, PSGUID_VIDEO, PIDVSI_COMPRESSION);
|
|
|
|
DEFINE_SCID(SCID_AUDIO_Format, PSGUID_AUDIO, PIDASI_FORMAT);
|
|
DEFINE_SCID(SCID_AUDIO_Duration, PSGUID_AUDIO, PIDASI_TIMELENGTH); //100ns units, not milliseconds. VT_UI8, not VT_UI4
|
|
DEFINE_SCID(SCID_AUDIO_Bitrate, PSGUID_AUDIO, PIDASI_AVG_DATA_RATE);
|
|
DEFINE_SCID(SCID_AUDIO_SampleRate, PSGUID_AUDIO, PIDASI_SAMPLE_RATE);
|
|
DEFINE_SCID(SCID_AUDIO_SampleSize, PSGUID_AUDIO, PIDASI_SAMPLE_SIZE);
|
|
DEFINE_SCID(SCID_AUDIO_ChannelCount, PSGUID_AUDIO, PIDASI_CHANNEL_COUNT);
|
|
|
|
DEFINE_SCID(SCID_IMAGE_Width, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_CX);
|
|
DEFINE_SCID(SCID_IMAGE_Height, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_CY);
|
|
DEFINE_SCID(SCID_IMAGE_Dimensions, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_DIMENSIONS);
|
|
DEFINE_SCID(SCID_IMAGE_FrameCount, PSGUID_IMAGESUMMARYINFORMATION, PIDISI_FRAME_COUNT);
|
|
|
|
|
|
// Docsummary props
|
|
const COLMAP g_CM_Category = { &SCID_Category, L"Category", VT_LPWSTR, FALSE}; // Alias property of Genre
|
|
|
|
// SummaryProps
|
|
const COLMAP g_CM_Author = { &SCID_Author, L"Author", VT_LPWSTR, FALSE}; // Alias property of Artist
|
|
const COLMAP g_CM_Title = { &SCID_Title, L"Title", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Comment = { &SCID_Comment, L"Description", VT_LPWSTR, TRUE};
|
|
|
|
// Music props
|
|
const COLMAP g_CM_Artist = { &SCID_MUSIC_Artist, L"Author", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Album = { &SCID_MUSIC_Album, L"AlbumTitle", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Year = { &SCID_MUSIC_Year, L"Year", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Track = { &SCID_MUSIC_Track, L"Track", VT_UI4, TRUE}; // NB: This is exposed as a WMT_ATTRTYPE_STRING for mp3. We may need to change it.
|
|
const COLMAP g_CM_Genre = { &SCID_MUSIC_Genre, L"Genre", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Lyrics = { &SCID_MUSIC_Lyrics, L"Lyrics", VT_LPWSTR, TRUE};
|
|
|
|
// Audio props
|
|
const COLMAP g_CM_Format = { &SCID_AUDIO_Format, L"Format", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_Duration = { &SCID_AUDIO_Duration, L"Duration", VT_UI8, TRUE};
|
|
const COLMAP g_CM_Bitrate = { &SCID_AUDIO_Bitrate, L"Bitrate", VT_UI4, TRUE};
|
|
const COLMAP g_CM_SampleRate = { &SCID_AUDIO_SampleRate, L"SampleRate", VT_UI4, TRUE}; // samples per sec
|
|
const COLMAP g_CM_SampleSize = { &SCID_AUDIO_SampleSize, L"SampleSize", VT_UI4, TRUE};
|
|
const COLMAP g_CM_ChannelCount ={ &SCID_AUDIO_ChannelCount, L"ChannelCount", VT_UI4, TRUE};
|
|
|
|
// Video props
|
|
const COLMAP g_CM_StreamName = { &SCID_VIDEO_StreamName, L"StreamName", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_FrameRate = { &SCID_VIDEO_FrameRate, L"FrameRate", VT_UI4, TRUE};
|
|
const COLMAP g_CM_SampleSizeV = { &SCID_VIDEO_SampleSize, L"SampleSize", VT_UI4, TRUE}; // different from audio sample simple
|
|
const COLMAP g_CM_BitrateV = { &SCID_VIDEO_Bitrate, L"Bitrate", VT_UI4, TRUE}; // different from audio bitrate
|
|
const COLMAP g_CM_Compression = { &SCID_VIDEO_Compression, L"Compression", VT_LPWSTR, TRUE};
|
|
|
|
// Image props
|
|
const COLMAP g_CM_Width = { &SCID_IMAGE_Width, L"Width", VT_UI4, TRUE};
|
|
const COLMAP g_CM_Height = { &SCID_IMAGE_Height, L"Height", VT_UI4, TRUE};
|
|
const COLMAP g_CM_Dimensions = { &SCID_IMAGE_Dimensions, L"Dimensions", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_FrameCount = { &SCID_IMAGE_FrameCount, L"FrameCount", VT_UI4, TRUE};
|
|
|
|
// DRM props
|
|
const COLMAP g_CM_Protected = { &SCID_DRM_Protected, L"Protected", VT_BOOL, TRUE};
|
|
const COLMAP g_CM_DRMDescription={&SCID_DRM_Description, L"DRMDescription", VT_LPWSTR, TRUE};
|
|
const COLMAP g_CM_PlayCount = { &SCID_DRM_PlayCount, L"PlayCount", VT_UI4, TRUE};
|
|
const COLMAP g_CM_PlayStarts = { &SCID_DRM_PlayStarts, L"PlayStarts", VT_FILETIME,TRUE};
|
|
const COLMAP g_CM_PlayExpires = { &SCID_DRM_PlayExpires, L"PlayExpires", VT_FILETIME,TRUE};
|
|
|
|
|
|
// Describes each of the property sets an IPropertySetStorage uses.
|
|
typedef struct {
|
|
GUID fmtid; // fmtid for this property set
|
|
const COLMAP **pcmProps; // List of all properties that exist in this set
|
|
ULONG cNumProps;
|
|
} PROPSET_INFO;
|
|
|
|
|
|
enum MUSICPROPSTG_AUTHLEVEL
|
|
{
|
|
AUTH = 0, NON_AUTH
|
|
};
|
|
|
|
enum PROPSTG_STATE
|
|
{
|
|
CLOSED = 0,
|
|
OPENED_SHARED,
|
|
OPENED_DENYREAD,
|
|
OPENED_DENYWRITE,
|
|
OPENED_DENYALL
|
|
};
|
|
|
|
class CMediaPropSetStg;
|
|
|
|
// Base property storage implementation.
|
|
class CMediaPropStorage : public IPropertyStorage, IQueryPropertyFlags
|
|
{
|
|
public:
|
|
// IUnknown
|
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
|
|
STDMETHODIMP_(ULONG) AddRef();
|
|
STDMETHODIMP_(ULONG) Release();
|
|
|
|
//IPropertyStorage
|
|
STDMETHODIMP ReadMultiple (ULONG cpspec, const PROPSPEC rgpspec[], PROPVARIANT rgvar[]);
|
|
STDMETHODIMP WriteMultiple (ULONG cpspec, PROPSPEC const rgpspec[], const PROPVARIANT rgvar[], PROPID propidNameFirst);
|
|
STDMETHODIMP DeleteMultiple(ULONG cpspec, PROPSPEC const rgpspec[]);
|
|
|
|
STDMETHODIMP ReadPropertyNames (ULONG cpspec, PROPID const rgpropid[], LPWSTR rglpwstrName[]);
|
|
STDMETHODIMP WritePropertyNames (ULONG cpspec, PROPID const rgpropid[], LPWSTR const rglpwstrName[]);
|
|
STDMETHODIMP DeletePropertyNames(ULONG cpspec, PROPID const rgpropid[]);
|
|
|
|
STDMETHODIMP SetClass(REFCLSID clsid);
|
|
STDMETHODIMP Commit(DWORD grfCommitFlags);
|
|
STDMETHODIMP Revert();
|
|
STDMETHODIMP Enum(IEnumSTATPROPSTG **ppenum);
|
|
STDMETHODIMP Stat(STATPROPSETSTG *pstatpropstg);
|
|
STDMETHODIMP SetTimes(FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime);
|
|
|
|
// IQueryPropertyFlags
|
|
STDMETHODIMP GetFlags(const PROPSPEC *pspec, SHCOLSTATEF *pcsFlags);
|
|
|
|
CMediaPropStorage(CMediaPropSetStg *ppssParent, CMediaPropStorage *ppsAuthority, REFFMTID fmtid, const COLMAP **ppcmPropInfo, DWORD cNumProps, DWORD dwMode, CRITICAL_SECTION *pcs);
|
|
|
|
HRESULT SetProperty(PROPSPEC *ppspec, PROPVARIANT *pvar);//called by the parent to set the initial data
|
|
HRESULT QuickLookup(PROPSPEC *ppspec, PROPVARIANT **ppvar);
|
|
|
|
private:
|
|
~CMediaPropStorage();
|
|
|
|
HRESULT Open(DWORD dwShareMode, DWORD dwOpenMode, IPropertyStorage **ppPropStg);
|
|
|
|
void _ResetPropStorage(); //Resets the Propstorage to a known empty state
|
|
HRESULT CopyPropStorageData(PROPVARIANT *pvarProps);
|
|
void OnClose();
|
|
HRESULT DoCommit(DWORD grfCommitFlags, FILETIME *ftFlushTime, PROPVARIANT *pVarProps, BOOL *pbDirtyFlags);//flush the data to the parent
|
|
HRESULT LookupProp(const PROPSPEC *pspec, const COLMAP **ppcmName, PROPVARIANT **ppvarReadData, PROPVARIANT **ppvarWriteData, BOOL **ppbDirty, BOOL bPropertySet);
|
|
BOOL IsDirectMode();
|
|
BOOL IsSpecialProperty(const PROPSPEC *pspec);
|
|
HRESULT _EnsureSlowPropertiesLoaded();
|
|
virtual BOOL _IsSlowProperty(const COLMAP *pPInfo);
|
|
|
|
LONG _cRef;
|
|
COLMAP const **_ppcmPropInfo;
|
|
PROPVARIANT *_pvarProps, *_pvarChangedProps;
|
|
PROPVARIANT _varCodePage;
|
|
BOOL *_pbDirtyFlags;
|
|
ULONG _cNumProps;
|
|
|
|
MUSICPROPSTG_AUTHLEVEL _authLevel;
|
|
CMediaPropStorage *_ppsAuthority;
|
|
CMediaPropSetStg *_ppssParent;
|
|
FMTID _fmtid;
|
|
FILETIME _ftLastCommit;
|
|
PROPSTG_STATE _state;
|
|
DWORD _dwMode;
|
|
BOOL _bRetrievedSlowProperties;
|
|
HRESULT _hrSlowProps;
|
|
CRITICAL_SECTION *_pcs; // The parent storage set's critical section.
|
|
|
|
friend class CMediaPropSetStg;
|
|
};
|
|
|
|
// Base property set storage implementation.
|
|
class CMediaPropSetStg : public IPersistFile, IPropertySetStorage, IWMReaderCallback
|
|
{
|
|
public:
|
|
CMediaPropSetStg();
|
|
|
|
// IUnknown
|
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
|
|
STDMETHODIMP_(ULONG) AddRef();
|
|
STDMETHODIMP_(ULONG) Release();
|
|
|
|
// IPersist
|
|
STDMETHODIMP GetClassID(CLSID *pClassID);
|
|
|
|
// IPersistFile
|
|
STDMETHODIMP IsDirty(void);
|
|
STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode);
|
|
STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember);
|
|
STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName);
|
|
STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName);
|
|
|
|
// IPropertySetStorage
|
|
STDMETHODIMP Create(REFFMTID fmtid, const CLSID * pclsid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** ppPropStg);
|
|
STDMETHODIMP Open(REFFMTID fmtid, DWORD grfMode, IPropertyStorage** ppPropStg);
|
|
STDMETHODIMP Delete(REFFMTID fmtid);
|
|
STDMETHODIMP Enum(IEnumSTATPROPSETSTG** ppenum);
|
|
|
|
// IWMReaderCallBack
|
|
STDMETHODIMP OnStatus(WMT_STATUS Staus, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext);
|
|
STDMETHODIMP OnSample(DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void* pcontext);
|
|
|
|
virtual HRESULT FlushChanges(REFFMTID fmtid, LONG cNumProps, const COLMAP **pcmapInfo, PROPVARIANT *pVarProps, BOOL *pbDirtyFlags);
|
|
HRESULT Init();
|
|
virtual BOOL _IsSlowProperty(const COLMAP *pPInfo);
|
|
|
|
protected:
|
|
HRESULT _ResolveFMTID(REFFMTID fmtid, CMediaPropStorage **ppps);
|
|
HRESULT _PopulateProperty(const COLMAP *pPInfo, PROPVARIANT *pvar);
|
|
|
|
BOOL _bIsWritable;
|
|
WCHAR _wszFile[MAX_PATH];
|
|
BOOL _bHasBeenPopulated;
|
|
BOOL _bSlowPropertiesExtracted;
|
|
HRESULT _hrSlowProps;
|
|
|
|
HRESULT _hrPopulated;
|
|
UINT _cPropertyStorages;
|
|
CMediaPropStorage **_propStg;
|
|
const PROPSET_INFO *_pPropStgInfo; // Indicates which propstorages to create, etc...
|
|
HANDLE _hFileOpenEvent;
|
|
~CMediaPropSetStg();
|
|
|
|
private:
|
|
HRESULT _ResetPropertySet();
|
|
HRESULT _CreatePropertyStorages();
|
|
virtual HRESULT _PopulatePropertySet();
|
|
virtual HRESULT _PopulateSlowProperties();
|
|
virtual HRESULT _PreCheck();
|
|
|
|
LONG _cRef;
|
|
DWORD _dwMode;
|
|
|
|
// This property handler needes to operate in a FTA because of the content indexing service. If
|
|
// we're created in an STA, it turns out they can't properly impersonate a user across apartment
|
|
// boundaries.
|
|
// This is a critical section we use to provide very "simple" synchronized access to our internal
|
|
// members. Basically, we just wrap every public interface member in Enter/Leave. The WMSDK
|
|
// doesn't throw any exceptions, so we don't need any try-finally's (and hopefully the AVI and WAV
|
|
// code doesn't either).
|
|
// All public interface members in the CMediaPropStorage class are also protected by this same
|
|
// critical section.
|
|
CRITICAL_SECTION _cs;
|
|
|
|
friend class CMediaPropStorage;
|
|
};
|
|
|
|
|
|
// Class used to enumerate through all COLMAPs for the properties supported by a propertysetstorage //
|
|
// Used internally by a PSS when populating properties.
|
|
class CEnumAllProps
|
|
{
|
|
public:
|
|
CEnumAllProps(const PROPSET_INFO *pPropSets, UINT cPropSets);
|
|
const COLMAP *Next();
|
|
|
|
private:
|
|
const PROPSET_INFO *_pPropSets;
|
|
UINT _cPropSets;
|
|
UINT _iPropSetPos;
|
|
UINT _iPropPos;
|
|
};
|
|
|
|
#endif //__MEDIAPROP_H__
|