// Author: Ryan Norton <wxprojects@comcast.net>
// Modified by:
// Created: 01/29/05
-// RCS-ID: $Id$
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifdef __BORLANDC__
-#pragma hdrstop
+ #pragma hdrstop
#endif
// disable "cast truncates constant value" for VARIANT_BOOL values
#pragma warning (disable:4310)
#endif
-//---------------------------------------------------------------------------
-// MediaCtrl include
-//---------------------------------------------------------------------------
+#if wxUSE_MEDIACTRL && wxUSE_ACTIVEX
+
#include "wx/mediactrl.h"
-//---------------------------------------------------------------------------
-// Compilation guard
-//---------------------------------------------------------------------------
-#if wxUSE_MEDIACTRL
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/dcclient.h"
+ #include "wx/timer.h"
+ #include "wx/math.h" // log10 & pow
+ #include "wx/stopwatch.h"
+#endif
-//---------------------------------------------------------------------------
-// WX Includes
-//---------------------------------------------------------------------------
-#include "wx/log.h" // wxLogDebug
-#include "wx/math.h" // log10 & pow
#include "wx/msw/private.h" // user info and wndproc setting/getting
-#include "wx/dcclient.h"
-#include "wx/timer.h"
#include "wx/dynlib.h"
-#include "wx/stopwatch.h"
//---------------------------------------------------------------------------
// wxActiveXContainer - includes all the COM-specific stuff we need
#endif
wxSize m_bestSize; // Cached size
-#ifdef __WXDEBUG__ // Stuff for getting useful debugging strings
+ // Stuff for getting useful debugging strings
+#if wxDEBUG_LEVEL
wxDynamicLibrary m_dllQuartz;
LPAMGETERRORTEXT m_lpAMGetErrorText;
wxString GetErrorString(HRESULT hrdsv);
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
+ wxEvtHandler* m_evthandler;
friend class wxAMMediaEvtHandler;
DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
bool m_bLoadEventSent; // Whether or not FinishLoaded was already called
// prevents it being called multiple times
- DECLARE_NO_COPY_CLASS(wxAMMediaEvtHandler)
+ wxDECLARE_NO_COPY_CLASS(wxAMMediaEvtHandler);
};
//===========================================================================
//---------------------------------------------------------------------------
// Usual debugging macros
//---------------------------------------------------------------------------
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
#define MAX_ERROR_TEXT_LEN 160
// Get the error string for Active Movie
{
return wxString::Format(wxT("DirectShow error \"%s\" \n")
wxT("(numeric %X)\n")
- wxT("occured"),
+ wxT("occurred"),
szError, (int)hrdsv);
}
else
{
return wxString::Format(wxT("Unknown error \n")
wxT("(numeric %X)\n")
- wxT("occured"),
+ wxT("occurred"),
(int)hrdsv);
}
}
wxAMMediaBackend::wxAMMediaBackend()
:m_pAX(NULL),
#ifdef __WXWINCE__
- m_pWMP(NULL)
+ m_pWMP(NULL),
#else
m_pAM(NULL),
- m_pMP(NULL)
+ m_pMP(NULL),
#endif
+ m_bestSize(wxDefaultSize)
{
+ m_evthandler = NULL;
}
//---------------------------------------------------------------------------
if (GetMP())
GetMP()->Release();
- m_ctrl->PopEventHandler(true);
+ if (m_evthandler)
+ {
+ m_ctrl->RemoveEventHandler(m_evthandler);
+ delete m_evthandler;
+ }
}
}
{
// First get the AMGetErrorText procedure in debug
// mode for more meaningful messages
-#ifdef __WXDEBUG__
- if ( m_dllQuartz.Load(_T("quartz.dll"), wxDL_VERBATIM) )
+#if wxDEBUG_LEVEL
+ if ( m_dllQuartz.Load(wxT("quartz.dll"), wxDL_VERBATIM) )
{
m_lpAMGetErrorText = (LPAMGETERRORTEXT)
m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
}
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
#endif
);
// Connect for events
- m_ctrl->PushEventHandler(new wxAMMediaEvtHandler(this));
+ m_evthandler = new wxAMMediaEvtHandler(this);
+ m_ctrl->PushEventHandler(m_evthandler);
//
// Here we set up wx-specific stuff for the default
return false;
}
+ m_bestSize = wxDefaultSize;
return true;
}
//---------------------------------------------------------------------------
void wxAMMediaBackend::FinishLoad()
{
- // Get the original video size
- GetAM()->get_ImageSourceWidth((long*)&m_bestSize.x);
- GetAM()->get_ImageSourceHeight((long*)&m_bestSize.y);
-
NotifyMovieLoaded();
}
bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
{
// Note that IMediaPlayer doesn't have a statusbar by
- // default but IActiveMovie does - so lets try to keep
- // the interface consistant
+ // default but IActiveMovie does - so let's try to keep
+ // the interface consistent.
if(!flags)
{
GetAM()->put_Enabled(VARIANT_FALSE);
}
//---------------------------------------------------------------------------
-// wxAMMediaBackend::GetVolume
+// wxAMMediaBackend::GetVolume and SetVolume()
//
-// Gets the volume through the IActiveMovie interface -
-// value ranges from 0 (MAX volume) to -10000 (minimum volume).
-// -100 per decibel (Logorithmic in 0.01db per step).
+// Notice that for the IActiveMovie interface value ranges from 0 (MAX volume)
+// to -10000 (minimum volume) and the scale is logarithmic in 0.01db per step.
//---------------------------------------------------------------------------
+
double wxAMMediaBackend::GetVolume()
{
long lVolume;
return 0.0;
}
- // Volume conversion from Greg Hazel
- double dVolume = (double)lVolume / 125;
+ double dVolume = lVolume / 2000.; // volume is now in [-5..0] range
+ dVolume = pow(10.0, dVolume); // [10^-5, 1]
+ dVolume -= 0.00001; // [0, 1-10^-5]
+ dVolume /= 1 - 0.00001; // [0, 1]
- // convert to 0 to 1
- dVolume = pow(10.0, dVolume/20.0);
- // handle -INF
- dVolume *= 1 + pow(10.0, -5.0);
- dVolume -= pow(10.0, -5.0);
return dVolume;
}
-//---------------------------------------------------------------------------
-// wxAMMediaBackend::SetVolume
-//
-// Sets the volume through the IActiveMovie interface -
-// value ranges from 0 (MAX volume) to -10000 (minimum volume).
-// -100 per decibel (Logorithmic in 0.01db per step).
-//---------------------------------------------------------------------------
bool wxAMMediaBackend::SetVolume(double dVolume)
{
- // Volume conversion from Greg Hazel
- long lVolume;
- // handle -INF
- dVolume *= 1 - pow(10.0, -5.0);
- dVolume += pow(10.0, -5.0);
- // convert to -100db to 0db
- dVolume = 20 * log10(dVolume);
- // scale to -10000 to 0
- lVolume = (long)(125 * dVolume);
-
- HRESULT hr = GetAM()->put_Volume( lVolume );
+ // inverse the transformation above
+ long lVolume = static_cast<long>(2000*log10(dVolume + (1 - dVolume)*0.00001));
+
+ HRESULT hr = GetAM()->put_Volume(lVolume);
if(FAILED(hr))
{
wxAMLOG(hr);
{
double outDuration;
HRESULT hr = GetAM()->get_Duration(&outDuration);
- if(FAILED(hr))
+ switch ( hr )
{
- wxAMLOG(hr);
- return 0;
- }
+ default:
+ wxAMLOG(hr);
+ // fall through
- // h,m,s,milli - outDuration is in 1 second (double)
- outDuration *= 1000;
- wxLongLong ll;
- ll.Assign(outDuration);
+ case S_FALSE:
+ return 0;
- return ll;
+ case S_OK:
+ // outDuration is in seconds, we need milliseconds
+#ifdef wxLongLong_t
+ return static_cast<wxLongLong_t>(outDuration * 1000);
+#else
+ // In principle it's possible to have video of duration greater
+ // than ~1193 hours which corresponds LONG_MAX in milliseconds so
+ // cast to wxLongLong first and multiply by 1000 only then to avoid
+ // the overflow (resulting in maximal duration of ~136 years).
+ return wxLongLong(static_cast<long>(outDuration)) * 1000;
+#endif
+ }
}
//---------------------------------------------------------------------------
wxLongLong* pLoadTotal)
{
#ifndef __WXWINCE__
- LONGLONG loadTotal = 0, loadProgress = 0;
- IUnknown* pFG;
- IAMOpenProgress* pOP;
- HRESULT hr;
- hr = m_pAM->get_FilterGraph(&pFG);
- if(SUCCEEDED(hr))
+ IUnknown* pFG = NULL;
+
+ HRESULT hr = m_pAM->get_FilterGraph(&pFG);
+
+ // notice that the call above may return S_FALSE and leave pFG NULL
+ if(SUCCEEDED(hr) && pFG)
{
+ IAMOpenProgress* pOP = NULL;
hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
- if(SUCCEEDED(hr))
- {
+ if(SUCCEEDED(hr) && pOP)
+ {
+ LONGLONG
+ loadTotal = 0,
+ loadProgress = 0;
hr = pOP->QueryProgress(&loadTotal, &loadProgress);
pOP->Release();
+
+ if(SUCCEEDED(hr))
+ {
+ *pLoadProgress = loadProgress;
+ *pLoadTotal = loadTotal;
+ pFG->Release();
+ return;
+ }
}
pFG->Release();
}
+#endif // !__WXWINCE__
- if(SUCCEEDED(hr))
- {
- *pLoadProgress = loadProgress;
- *pLoadTotal = loadTotal;
- }
- else
-#endif
- {
- // When not loading from a URL QueryProgress will return
- // E_NOINTERFACE or whatever
- // wxAMFAIL(hr);
- *pLoadProgress = 0;
- *pLoadTotal = 0;
- }
+ *pLoadProgress = 0;
+ *pLoadTotal = 0;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
wxSize wxAMMediaBackend::GetVideoSize() const
{
- return m_bestSize;
+ if (m_bestSize == wxDefaultSize)
+ {
+ wxAMMediaBackend* self = wxConstCast(this, wxAMMediaBackend);
+ long w = 0;
+ long h = 0;
+
+ self->GetAM()->get_ImageSourceWidth(&w);
+ self->GetAM()->get_ImageSourceHeight(&h);
+
+ if (w != 0 && h != 0)
+ self->m_bestSize.Set(w, h);
+ else
+ return wxSize(0,0);
+ }
+
+ return m_bestSize;
}
//---------------------------------------------------------------------------
// End of wxAMMediaBackend
//---------------------------------------------------------------------------
-// in source file that contains stuff you don't directly use
-#include "wx/html/forcelnk.h"
-FORCE_LINK_ME(wxmediabackend_am)
+// Allow the user code to use wxFORCE_LINK_MODULE() to ensure that this object
+// file is not discarded by the linker.
+#include "wx/link.h"
+wxFORCE_LINK_THIS_MODULE(wxmediabackend_am)
-//---------------------------------------------------------------------------
-// End wxMediaCtrl Compilation Guard and this file
-//---------------------------------------------------------------------------
-#endif // wxUSE_MEDIACTRL
+#endif // wxUSE_MEDIACTRL && wxUSE_ACTIVEX