//==========================================================================; // // ksextend.h : additional infrastructure to extend the ks stuff so that it // works nicely from c++ // Copyright (c) Microsoft Corporation 1995-1997. // ///////////////////////////////////////////////////////////////////////////// #pragma once #ifndef KSEXTEND_H #define KSEXTEND_H #include #include #include #include //NOTE: ksproxy won't define IKsPin without __STREAMS__ and then it requires CMediaType from // mtype.h #define __STREAMS__ // for some reason in the area of media types the am guys have severely blurred the distinction // between their public client interface for apps and their internal class hierarchy for building // filters. mtype.h and mtype.cpp should be combined and placed into \sdk\include instead of // classes\base\include. they should also put an ifdef MMSYSTEM_H around their definitions // that use WAVEFORMATEX, so its not necessary to put all that stuff into your app if you're not // using it. to work around this i'm using the following hack: #include #include #include #include const int KSMEDIUM_INPUTFLAG = 0x1; typedef unsigned char UBYTE; typedef CComQIPtr PQKSPropertySet; typedef CComQIPtr PQKSPin; class KSPinMedium : public KSIDENTIFIER { public: KSPinMedium() { memset(this, 0, sizeof(*this)); } KSPinMedium(REFGUID SetInit, ULONG IdInit, ULONG FlagsInit) { Set = SetInit; Id = IdInit; Flags = FlagsInit; } KSPinMedium(const KSPinMedium &rhs) { Set = rhs.Set; Id = rhs.Id; Flags = rhs.Flags; } KSPinMedium(const KSIDENTIFIER &rhs) { Set = rhs.Set; Id = rhs.Id; Flags = rhs.Flags; } KSPinMedium& operator=(const KSPinMedium &rhs) { if (&rhs != this) { Set = rhs.Set; Id = rhs.Id; Flags = rhs.Flags; } return *this; } #if 0 // hopefully we can get the ks guys to fix their anonymous union problem // so that we don't need this hack operator KSIDENTIFIER() { return *(reinterpret_cast(this)); } #endif KSPinMedium& operator=(const KSIDENTIFIER &rhs) { if (&rhs != reinterpret_cast(this)) { Set = rhs.Set; Id = rhs.Id; Flags = rhs.Flags; } return *this; } bool operator==(const KSPinMedium &rhs) const { // NOTE: at some point there will be a flag in Flags to // indicate whether or not Id is significant for this object // at that point this method will need to change return (Id == rhs.Id && Set == rhs.Set); } bool operator!=(const KSPinMedium &rhs) const { // NOTE: at some point there will be a flag in Flags to // indicate whether or not Id is significant for this object // at that point this method will need to change return !(*this == rhs); } }; #ifdef _DEBUG inline tostream &operator<<(tostream &dc, const KSPinMedium &g) { GUID2 g2(g.Set); dc << _T("KsPinMedium( "); g2.Dump(dc); dc << _T(", ") << hexdump(g.Id) << _T(", ") << hexdump(g.Flags) << _T(")"); return dc; } #if 0 inline CDumpContext &operator<<(CDumpContext &dc, const KSPinMedium &g) { GUID2 g2(g.Set); dc << "KsPinMedium( "; g2.Dump(dc); dc << ", " << hexdump(g.Id) << ", " << hexdump(g.Flags) << ")"; return dc; } template<> struct equal_to { bool operator()(const KSPinMedium& _X, const KSPinMedium& _Y) const { TraceDump << "equal_to x = " << _X << " y = " << _Y; return (_X == _Y); } }; #endif #endif const KSPinMedium NULL_MEDIUM(GUID_NULL, 0, 0); const KSPinMedium HOST_MEMORY_MEDIUM(KSMEDIUMSETID_Standard, 0, 0); // this is basically a CComQIPtr with appropriate CoMem* allocate/copy semantics // instead of refcount semantics and without the QI stuff. class PQKsMultipleItem { public: KSMULTIPLE_ITEM *p; PQKsMultipleItem() : p(NULL) {} virtual ~PQKsMultipleItem() { if (p) { CoTaskMemFree(p); p = NULL; } } operator KSMULTIPLE_ITEM*() const {return p;} KSMULTIPLE_ITEM& operator*() const {_ASSERTE(p!=NULL); return *p; } KSMULTIPLE_ITEM ** operator&() {ASSERT(p == NULL); return &p; } KSMULTIPLE_ITEM * operator->() const {_ASSERTE(p!=NULL); return p; } PQKsMultipleItem * address(void) { return this; } const PQKsMultipleItem * const_address(void) const { return this; } // this is expensive. don't do it unless you have to. PQKsMultipleItem& operator=(const KSMULTIPLE_ITEM &d) { if (&d != p) { if (p) { CoTaskMemFree(p); } p = reinterpret_cast(CoTaskMemAlloc(d.Size)); memcpy(p, &d, d.Size); } return *this; } PQKsMultipleItem& operator=(const KSMULTIPLE_ITEM *pd) { if (pd != p) { if (p) { CoTaskMemFree(p); } p = reinterpret_cast(CoTaskMemAlloc(pd->Size)); memcpy(p, pd, pd->Size); } return *this; } PQKsMultipleItem& operator=(const PQKsMultipleItem &d) { if (d.const_address() != this) { if (p) { CoTaskMemFree(p); } p = reinterpret_cast(CoTaskMemAlloc(d.p->Size)); memcpy(p, d.p, d.p->Size); } return *this; } PQKsMultipleItem& operator=(int d) { if (p) { CoTaskMemFree(p); p = NULL; } return *this; } #if 0 bool operator==(const PQKsMultipleItem &d) const { return p->majortype == d.p->majortype && (p->subtype == GUID_NULL || d.p->subtype == GUID_NULL || p->subtype == d.p->subtype); } bool operator!=(const PQKsMultipleItem &d) const { return !(*this == d); } #endif private: // i don't want spend the time to do a layered refcounted implementation here // but since these are CoTaskMem alloc'd we can't have multiple ref's without // a high risk of leaks. so we're just going to disallow the copy constructor // since copying is expensive anyway. we will allow explicit assignment which will // do a copy PQKsMultipleItem(const PQKsMultipleItem &d); }; // this is a stl based template for containing KSMULTIPLEITEM lists // i've only implemented the stuff i need for certain of the stl predicates so this // isn't a complete collection with a true random access or bidirectional iterator // furthermore this won't work correctly with hterogeneous KSMULTIPLEITEM lists it // also won't work right for KSMI lists that have sizes and count headers in the sub items. // it could be easily extended to do all of these things but i don't have time and all // i need it for is mediums // Base is smart pointer wrapper class being contained in this container // Base_Inner is actual wrapped class that the smart pointer class contains template > class KsMultipleItem_Sequence : public PQKsMultipleItem { public: typedef Allocator::value_type value_type; typedef Allocator::size_type size_type; typedef Allocator::difference_type difference_type; typedef Allocator allocator_type; typedef Allocator::pointer value_ptr; typedef Allocator::const_pointer value_cptr; typedef Allocator::reference reference; typedef Allocator::const_reference const_reference; // CLASS iterator class iterator; friend class iterator; class iterator : public std::_Bidit { public: iterator(KsMultipleItem_Sequence *outerinit = NULL, value_type *currentinit = NULL) : outer(outerinit), current(currentinit) {} iterator(iterator &e) : current(e.current), outer(e.outer) {} reference operator*() const {return *current;} value_ptr operator->() const {return current; } iterator& operator++() { if (current) { current++; if (current >= reinterpret_cast(reinterpret_cast(outer->p) + outer->p->Size)) { current = NULL; } } else { current = reinterpret_cast(const_cast(reinterpret_cast(outer->p)) + sizeof(KSMULTIPLE_ITEM)); } return *this; } iterator& operator++(int) { iterator Tmp = *this; ++*this; return Tmp; } iterator& operator--() { if (current) { current--; if (current < reinterpret_cast(const_cast(reinterpret_cast(outer->p)) + sizeof(KSMULTIPLE_ITEM))) { current = NULL; } } else { current = reinterpret_cast(reinterpret_cast(outer->p) + (outer->p->Size - sizeof(value_type))); } return (*this); } iterator operator--(int) { iterator _Tmp = *this; --*this; return (_Tmp); } bool operator==(const iterator& rhs) const {return (current == rhs.current); } bool operator!=(const iterator& rhs) const {return (!(*this == rhs)); } protected: value_type *current; const KsMultipleItem_Sequence *outer; }; // CLASS const_iterator class const_iterator; friend class const_iterator; class const_iterator : public iterator { public: const_iterator(const KsMultipleItem_Sequence *outerinit = NULL, value_type *currentinit = NULL) { outer = outerinit; current = currentinit; } const_iterator(const_iterator &e) { current = e.current; outer = e.outer; } const_reference operator*() const {return iterator::operator*(); } value_cptr operator->() const {return iterator::operator->(); } const_iterator& operator++() { iterator::operator++(); return *this;} const_iterator operator++(int) { const_iterator Tmp = *this; ++*this; return (Tmp); } const_iterator& operator--() {iterator::operator--(); return (*this); } const_iterator operator--(int) { const_iterator Tmp = *this; --*this; return (Tmp); } bool operator==(const const_iterator& rhs) const {return iterator::operator==(rhs); } bool operator!=(const const_iterator& rhs) const {return (!(*this == rhs)); } }; KsMultipleItem_Sequence() {} virtual ~KsMultipleItem_Sequence() {} iterator begin() { return iterator(this, ((p->Count) ? reinterpret_cast(reinterpret_cast(p) + sizeof(KSMULTIPLE_ITEM)) : NULL)); } const_iterator begin() const { return const_iterator(this, ((p->Count) ? reinterpret_cast(reinterpret_cast(p) + sizeof(KSMULTIPLE_ITEM)) : NULL)); } iterator end() { return iterator(); } const_iterator end() const { return const_iterator(); } size_type size() const { return p->Count; } private: // no copy constructor, its too expensive. see PQKsMultiple item for further details KsMultipleItem_Sequence(KsMultipleItem_Sequence &a); KsMultipleItem_Sequence(PQKsMultipleItem &a); }; typedef KsMultipleItem_Sequence KSMediumList; #endif // end of file - ksextend.h