Ryan's cumulative wxActiveX and media control patch (1427775)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37461 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-02-10 19:37:40 +00:00
parent dcae64c221
commit 557002cf81
19 changed files with 6828 additions and 1099 deletions

View File

@@ -39,6 +39,7 @@
@echo USE_THREADS=$(USE_THREADS) >>$(BUILD_CFG_FILE) @echo USE_THREADS=$(USE_THREADS) >>$(BUILD_CFG_FILE)
@echo USE_GUI=$(USE_GUI) >>$(BUILD_CFG_FILE) @echo USE_GUI=$(USE_GUI) >>$(BUILD_CFG_FILE)
@echo USE_HTML=$(USE_HTML) >>$(BUILD_CFG_FILE) @echo USE_HTML=$(USE_HTML) >>$(BUILD_CFG_FILE)
@echo USE_MEDIA=$(USE_MEDIA) >>$(BUILD_CFG_FILE)
@echo USE_ODBC=$(USE_ODBC) >>$(BUILD_CFG_FILE) @echo USE_ODBC=$(USE_ODBC) >>$(BUILD_CFG_FILE)
@echo USE_OPENGL=$(USE_OPENGL) >>$(BUILD_CFG_FILE) @echo USE_OPENGL=$(USE_OPENGL) >>$(BUILD_CFG_FILE)
@echo USE_QA=$(USE_QA) >>$(BUILD_CFG_FILE) @echo USE_QA=$(USE_QA) >>$(BUILD_CFG_FILE)

View File

@@ -180,6 +180,14 @@ Acts according to BUILD by default.
</description> </description>
</option> </option>
<option name="USE_MEDIA">
<values>0,1</values>
<default-value>1</default-value>
<description>
Build multimedia library (USE_GUI must be 1)?
</description>
</option>
<option name="USE_XRC"> <option name="USE_XRC">
<values>0,1</values> <values>0,1</values>
<default-value>1</default-value> <default-value>1</default-value>
@@ -403,6 +411,7 @@ Set the version of your Mingw installation here.
<set var="RUNTIME_LIBS">dynamic</set> <set var="RUNTIME_LIBS">dynamic</set>
<set var="OFFICIAL_BUILD">0</set> <set var="OFFICIAL_BUILD">0</set>
<set var="USE_HTML">1</set> <set var="USE_HTML">1</set>
<set var="USE_MEDIA">1</set>
<set var="USE_XRC">1</set> <set var="USE_XRC">1</set>
<set var="USE_OPENGL">1</set> <set var="USE_OPENGL">1</set>
<set var="USE_ODBC">1</set> <set var="USE_ODBC">1</set>

View File

@@ -2657,7 +2657,8 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
</set> </set>
<set var="MEDIA_MSW_SRC" hints="files"> <set var="MEDIA_MSW_SRC" hints="files">
src/msw/mediactrl.cpp src/msw/mediactrl_am.cpp
src/msw/mediactrl_wmp10.cpp
src/msw/ole/activex.cpp src/msw/ole/activex.cpp
</set> </set>
<set var="MEDIA_MSW_HDR" hints="files"> <set var="MEDIA_MSW_HDR" hints="files">

View File

@@ -102,7 +102,7 @@
<!-- ================================================================= --> <!-- ================================================================= -->
<dll id="mediadll" template="wx_dll" <dll id="mediadll" template="wx_dll"
cond="SHARED=='1' and USE_GUI=='1' and MONOLITHIC=='0'"> cond="SHARED=='1' and USE_MEDIA=='1' and USE_GUI=='1' and MONOLITHIC=='0'">
<define>WXUSINGDLL</define> <define>WXUSINGDLL</define>
<define>WXMAKINGDLL_MEDIA</define> <define>WXMAKINGDLL_MEDIA</define>
<sources>$(MEDIA_SRC)</sources> <sources>$(MEDIA_SRC)</sources>
@@ -112,7 +112,7 @@
</dll> </dll>
<lib id="medialib" template="wx_lib" <lib id="medialib" template="wx_lib"
cond="SHARED=='0' and USE_GUI=='1' and MONOLITHIC=='0'"> cond="SHARED=='0' and USE_MEDIA=='1' and USE_GUI=='1' and MONOLITHIC=='0'">
<sources>$(MEDIA_SRC)</sources> <sources>$(MEDIA_SRC)</sources>
<msvc-headers>$(MEDIA_HDR)</msvc-headers> <msvc-headers>$(MEDIA_HDR)</msvc-headers>
</lib> </lib>

View File

@@ -422,6 +422,7 @@ if test $DEBUG_CONFIGURE = 1; then
DEFAULT_wxUSE_TEXTFILE=no DEFAULT_wxUSE_TEXTFILE=no
DEFAULT_wxUSE_SOUND=no DEFAULT_wxUSE_SOUND=no
DEFAULT_wxUSE_MEDIACTRL=no DEFAULT_wxUSE_MEDIACTRL=no
DEFAULT_wxUSE_GSTREAMER8=no
DEFAULT_wxUSE_INTL=no DEFAULT_wxUSE_INTL=no
DEFAULT_wxUSE_CONFIG=no DEFAULT_wxUSE_CONFIG=no
DEFAULT_wxUSE_FONTMAP=no DEFAULT_wxUSE_FONTMAP=no
@@ -624,6 +625,7 @@ else
DEFAULT_wxUSE_TEXTFILE=yes DEFAULT_wxUSE_TEXTFILE=yes
DEFAULT_wxUSE_SOUND=yes DEFAULT_wxUSE_SOUND=yes
DEFAULT_wxUSE_MEDIACTRL=no DEFAULT_wxUSE_MEDIACTRL=no
DEFAULT_wxUSE_GSTREAMER8=no
DEFAULT_wxUSE_INTL=yes DEFAULT_wxUSE_INTL=yes
DEFAULT_wxUSE_CONFIG=yes DEFAULT_wxUSE_CONFIG=yes
DEFAULT_wxUSE_FONTMAP=yes DEFAULT_wxUSE_FONTMAP=yes
@@ -935,6 +937,7 @@ WX_ARG_ENABLE(timer, [ --enable-timer use wxTimer class], wxUS
WX_ARG_ENABLE(unicode, [ --enable-unicode compile wxString with Unicode support], wxUSE_UNICODE) WX_ARG_ENABLE(unicode, [ --enable-unicode compile wxString with Unicode support], wxUSE_UNICODE)
WX_ARG_ENABLE(sound, [ --enable-sound use wxSound class], wxUSE_SOUND) WX_ARG_ENABLE(sound, [ --enable-sound use wxSound class], wxUSE_SOUND)
WX_ARG_ENABLE(mediactrl, [ --enable-mediactrl use wxMediaCtrl class], wxUSE_MEDIACTRL) WX_ARG_ENABLE(mediactrl, [ --enable-mediactrl use wxMediaCtrl class], wxUSE_MEDIACTRL)
WX_ARG_ENABLE(gstreamer8, [ --enable-gstreamer8 force GStreamer 0.8 instead of 0.10 with the wxMediaCtrl class on unix], wxUSE_GSTREAMER8)
WX_ARG_ENABLE(wxprintfv, [ --enable-wxprintfv use wxWidgets implementation of vprintf()], wxUSE_EXPERIMENTAL_PRINTF) WX_ARG_ENABLE(wxprintfv, [ --enable-wxprintfv use wxWidgets implementation of vprintf()], wxUSE_EXPERIMENTAL_PRINTF)
WX_ARG_ENABLE(zipstream, [ --enable-zipstream use wxZip streams], wxUSE_ZIPSTREAM) WX_ARG_ENABLE(zipstream, [ --enable-zipstream use wxZip streams], wxUSE_ZIPSTREAM)
@@ -6754,6 +6757,8 @@ dnl ---------------------------------------------------------------------------
dnl wxMediaCtrl dnl wxMediaCtrl
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
USE_MEDIA=0
if test "$wxUSE_MEDIACTRL" = "yes"; then if test "$wxUSE_MEDIACTRL" = "yes"; then
dnl ----------------------------------------------------------------------- dnl -----------------------------------------------------------------------
dnl GStreamer dnl GStreamer
@@ -6762,77 +6767,57 @@ if test "$wxUSE_MEDIACTRL" = "yes"; then
wxUSE_GSTREAMER="yes" wxUSE_GSTREAMER="yes"
dnl ------------------------------------------------------------------- dnl -------------------------------------------------------------------
dnl Test for gstreamer module from pkg-config dnl Test for at least 0.8 gstreamer module from pkg-config
dnl ------------------------------------------------------------------- dnl Even totem doesn't accept 0.9 evidently.
PKG_CHECK_MODULES(GSTREAMER, gstreamer-0.8,
[
CPPFLAGS="$GSTREAMER_CFLAGS $CPPFLAGS"
LIBS="$LIBS $GSTREAMER_LIBS -lgstplay-0.8"
],
[
AC_MSG_WARN([GStreamer installation not found])
wxUSE_GSTREAMER="no"
])
dnl -------------------------------------------------------------------
dnl Perform a check for a GStreamer element using gst-inspect
dnl Thomas Vander Stichele <thomas at apestaart dot org>
dnl Last modification: 25/01/2005
dnl dnl
dnl AM_GST_ELEMENT_CHECK(ELEMENT-NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) dnl So, we first check to see if 0.10 if available - if not we
dnl try the older 0.8 version
dnl ------------------------------------------------------------------- dnl -------------------------------------------------------------------
AC_DEFUN([AM_GST_ELEMENT_CHECK], GST_VERSION_MAJOR=0
[ GST_VERSION_MINOR=10
if test "x$GST_INSPECT" == "x"; then GST_VERSION_RELEASE=0
AC_CHECK_PROG(GST_INSPECT, gst-inspect, gst-inspect, []) GSTREAMER_REQ=$GST_VERSION_MAJOR.$GST_VERSION_MINOR.$GST_VERSION_RELEASE
fi GST_MAJORMINOR=$GST_VERSION_MAJOR.$GST_VERSION_MINOR
if test "x$GST_INSPECT" != "x"; then if test "$wxUSE_GSTREAMER8" = "no"; then
AC_MSG_CHECKING(GStreamer element $1) PKG_CHECK_MODULES(GST, gstreamer-$GST_MAJORMINOR
if [ $GST_INSPECT $1 > /dev/null 2> /dev/null ]; then gstreamer-plugins-base-$GST_MAJORMINOR
AC_MSG_RESULT(found.) gconf-2.0,
$2
else
AC_MSG_RESULT(not found.)
$3
fi
fi
])
dnl -------------------------------------------------------------------
dnl Test for x video sink (video useless without)
dnl -------------------------------------------------------------------
AM_GST_ELEMENT_CHECK(xvimagesink,[],
[ [
wxUSE_GSTREAMER="no" CPPFLAGS="$GST_CFLAGS $CPPFLAGS"
AC_MSG_WARN([x video sink not found - cannot use GStreamer]) LIBS="$LIBS $GST_LIBS -lgstinterfaces-$GST_MAJORMINOR"
])
dnl -------------------------------------------------------------------
dnl Check for gstplay-0.8 lib and corresponding x overlay header
dnl -------------------------------------------------------------------
AC_CHECK_HEADER(gst/xoverlay/xoverlay.h, [],
[
wxUSE_GSTREAMER="no"
AC_MSG_WARN([xoverlay header not found, cannot use GStreamer])
], ],
[#include <gst/gst.h>]) [
GST_VERSION_MINOR=8
AC_MSG_CHECKING([for gstplay 0.8]) ])
WX_PATH_FIND_LIBRARIES([$SEARCH_LIB],gstplay-0.8)
if test "$ac_find_libraries" = "" ; then
AC_MSG_RESULT([no])
wxUSE_GSTREAMER="no"
else else
AC_MSG_RESULT([yes]) GST_VERSION_MINOR=8
fi fi
GSTREAMER_REQ=$GST_VERSION_MAJOR.$GST_VERSION_MINOR.$GST_VERSION_RELEASE
GST_MAJORMINOR=$GST_VERSION_MAJOR.$GST_VERSION_MINOR
if test x$GST_VERSION_MINOR = x8; then
PKG_CHECK_MODULES(GST, gstreamer-$GST_MAJORMINOR
gstreamer-interfaces-$GST_MAJORMINOR
gstreamer-gconf-$GST_MAJORMINOR,
[
CPPFLAGS="$GST_CFLAGS $CPPFLAGS"
LIBS="$LIBS $GST_LIBS"
],
[
AC_MSG_WARN([Proper GStreamer .8/.10 installation not found])
wxUSE_GSTREAMER="no"
])
fi
if test "$wxUSE_GSTREAMER" = "yes"; then if test "$wxUSE_GSTREAMER" = "yes"; then
AC_DEFINE(wxUSE_GSTREAMER) AC_DEFINE(wxUSE_GSTREAMER)
AC_MSG_RESULT([GStreamer detection successful]) AC_MSG_RESULT([GStreamer detection successful])
fi fi
fi fi
USE_MEDIA=1
SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS mediaplayer" SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS mediaplayer"
AC_DEFINE(wxUSE_MEDIACTRL) AC_DEFINE(wxUSE_MEDIACTRL)
fi fi

View File

@@ -0,0 +1,236 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: activexcontainer.tex
%% Purpose: wxActiveXContainer docs
%% Author: Ryan Norton <wxprojects@comcast.net>
%% Modified by:
%% Created: 01/30/2005
%% RCS-ID: $Id$
%% Copyright: (c) Ryan Norton
%% License: wxWindows license
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{\class{wxActiveXContainer}}\label{wxactivexcontainer}
wxActiveXContainer is a host for an activex control on Windows (and
as such is a platform-specific class). Note that the HWND that the class
contains is the actual HWND of the activex control so using dynamic events
and connecting to wxEVT\_SIZE, for example, will recieve the actual size
message sent to the control.
It is somewhat similar to the ATL class CAxWindow in operation.
The size of the activex control's content is generally gauranteed to be that
of the client size of the parent of this wxActiveXContainer.
You can also process activex events through wxEVT\_ACTIVEX or the
corresponding message map macro EVT\_ACTIVEX.
\wxheading{See also}
\helpref{wxActiveXEvent}{wxactivexevent}
\wxheading{Derived from}
\helpref{wxControl}{wxcontrol}
\wxheading{Include files}
<wx/msw/ole/activex.h>
\wxheading{Example}
This is an example of how to use the Adobe Acrobat Reader ActiveX control to read PDF files
(requires Acrobat Reader 4 and up). Controls like this are typically found and dumped from
OLEVIEW.exe that is distributed with Microsoft Visual C++. This example also demonstrates
how to create a backend for \helpref{wxMediaCtrl}{wxmediactrl}.
\begin{verbatim}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxPDFMediaBackend
//
// http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACOverview.pdf
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "wx/mediactrl.h" // wxMediaBackendCommonBase
#include "wx/msw/ole/activex.h" // wxActiveXContainer
#include "wx/msw/ole/automtn.h" // wxAutomationObject
const IID DIID__DPdf = {0xCA8A9781,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
const IID DIID__DPdfEvents = {0xCA8A9782,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
const CLSID CLSID_Pdf = {0xCA8A9780,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
class WXDLLIMPEXP_MEDIA wxPDFMediaBackend : public wxMediaBackendCommonBase
{
public:
wxPDFMediaBackend() : m_pAX(NULL) {}
virtual ~wxPDFMediaBackend()
{
if(m_pAX)
{
m_pAX->DissociateHandle();
delete m_pAX;
}
}
virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
IDispatch* pDispatch;
if( ::CoCreateInstance(CLSID_Pdf, NULL,
CLSCTX_INPROC_SERVER,
DIID__DPdf, (void**)&pDispatch) != 0 )
return false;
m_PDF.SetDispatchPtr(pDispatch); // wxAutomationObject will release itself
if ( !ctrl->wxControl::Create(parent, id, pos, size,
(style & ~wxBORDER_MASK) | wxBORDER_NONE,
validator, name) )
return false;
m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
m_pAX = new wxActiveXContainer(ctrl,
DIID__DPdf,
pDispatch);
wxPDFMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
return true;
}
virtual bool Play()
{
return true;
}
virtual bool Pause()
{
return true;
}
virtual bool Stop()
{
return true;
}
virtual bool Load(const wxString& fileName)
{
if(m_PDF.CallMethod(wxT("LoadFile"), fileName).GetBool())
{
m_PDF.CallMethod(wxT("setCurrentPage"), wxVariant((long)0));
NotifyMovieLoaded(); // initial refresh
wxSizeEvent event;
m_pAX->OnSize(event);
return true;
}
return false;
}
virtual bool Load(const wxURI& location)
{
return m_PDF.CallMethod(wxT("LoadFile"), location.BuildUnescapedURI()).GetBool();
}
virtual bool Load(const wxURI& WXUNUSED(location),
const wxURI& WXUNUSED(proxy))
{
return false;
}
virtual wxMediaState GetState()
{
return wxMEDIASTATE_STOPPED;
}
virtual bool SetPosition(wxLongLong where)
{
m_PDF.CallMethod(wxT("setCurrentPage"), wxVariant((long)where.GetValue()));
return true;
}
virtual wxLongLong GetPosition()
{
return 0;
}
virtual wxLongLong GetDuration()
{
return 0;
}
virtual void Move(int WXUNUSED(x), int WXUNUSED(y),
int WXUNUSED(w), int WXUNUSED(h))
{
}
wxSize GetVideoSize() const
{
return wxDefaultSize;
}
virtual double GetPlaybackRate()
{
return 0;
}
virtual bool SetPlaybackRate(double)
{
return false;
}
virtual double GetVolume()
{
return 0;
}
virtual bool SetVolume(double)
{
return false;
}
virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags)
{
if(flags)
{
m_PDF.CallMethod(wxT("setShowToolbar"), true);
m_PDF.CallMethod(wxT("setShowScrollbars"), true);
}
else
{
m_PDF.CallMethod(wxT("setShowToolbar"), false);
m_PDF.CallMethod(wxT("setShowScrollbars"), false);
}
return true;
}
wxActiveXContainer* m_pAX;
wxAutomationObject m_PDF;
DECLARE_DYNAMIC_CLASS(wxPDFMediaBackend)
};
IMPLEMENT_DYNAMIC_CLASS(wxPDFMediaBackend, wxMediaBackend);
\end{verbatim}
Put this in one of your existant source files and then create a wxMediaCtrl with
\begin{verbatim}
//[this] is the parent window, "myfile.pdf" is the PDF file to open
wxMediaCtrl* mymediactrl = new wxMediaCtrl(this, wxT("myfile.pdf"), wxID_ANY,
wxDefaultPosition, wxSize(300,300),
0, wxT("wxPDFMediaBackend"));
\end{verbatim}
\latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxActiveXContainer::wxActiveXContainer}\label{wxactivexcontainerwxactivexcontainer}
\func{}{wxActiveXContainer}{
\param{wxWindow* }{parent},
\param{REFIID }{iid},
\param{IUnknown* }{pUnk},
}
Creates this activex container.
\docparam{parent}{parent of this control. Must not be NULL.}
\docparam{iid}{COM IID of pUnk to query. Must be a valid interface to an activex control.}
\docparam{pUnk}{Interface of activex control}

View File

@@ -0,0 +1,75 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: activexevt.tex
%% Purpose: wxActiveXEvent docs
%% Author: Ryan Norton <wxprojects@comcast.net>
%% Modified by:
%% Created: 01/30/2005
%% RCS-ID: $Id$
%% Copyright: (c) Ryan Norton
%% License: wxWindows license
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{\class{wxActiveXEvent}}\label{wxactivexevent}
An event class for handling activex events passed from
\helpref{wxActiveXContainer}{wxactivexcontainer}. ActiveX events are basically
a function call with the parameters passed through an array of wxVariants along
with a return value that is a wxVariant itself. What type the parameters or
return value are depends on the context (i.e. what the .idl specifies).
Note that unlike the third party wxActiveX function names are not supported.
\wxheading{Derived from}
\helpref{wxCommandEvent}{wxcommandevent}
\wxheading{Include files}
<wx/msw/ole/activex.h>
\wxheading{Event table macros}
\twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt
\twocolitem{{\bf EVT\_ACTIVEX(func)}}{
Sent when the activex control hosted by \helpref{wxActiveXContainer}{wxactivexcontainer}
recieves an activex event.}
\end{twocollist}
\latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxActiveXEvent::ParamCount}\label{wxactivexeventparamcount}
\constfunc{int}{ParamCount}{\void}
Obtains the number of parameters passed through the activex event.
\membersection{wxActiveXEvent::ParamType}\label{wxactivexeventparamtype}
\constfunc{wxString}{ParamType}{\param{int }{idx}}
Obtains the param type of the param number idx specifies as a string.
\membersection{wxActiveXEvent::ParamName}\label{wxactivexeventparamname}
\constfunc{wxString}{ParamName}{\param{int }{idx}}
Obtains the param name of the param number idx specifies as a string.
\membersection{wxActiveXEvent::operator[]}\label{wxactivexeventoparray}
\func{wxVariant&}{operator[]}{\param{int }{idx}}
Obtains the actual parameter value specified by idx.
\membersection{wxActiveXEvent::GetDispatchId}\label{wxactivexeventgetdispatchid}
\constfunc{DISPID}{GetDispatchId}{\param{int }{idx}}
Returns the dispatch id of this activex event. This is the numeric value from
the .idl file specified by the id().

View File

@@ -8,6 +8,8 @@
\input accel.tex \input accel.tex
\input accessible.tex \input accessible.tex
\input activevt.tex \input activevt.tex
\input activexcontainer.tex
\input activexevt.tex
\input app.tex \input app.tex
\input archive.tex \input archive.tex
\input array.tex \input array.tex

View File

@@ -18,6 +18,10 @@ wxMediaCtrl uses native backends to render media, for example on Windows
there is a ActiveMovie/DirectShow backend, and on Macintosh there is a there is a ActiveMovie/DirectShow backend, and on Macintosh there is a
QuickTime backend. QuickTime backend.
\wxheading{See also}
\helpref{wxMediaEvent}{wxmediaevent}
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxControl}{wxcontrol} \helpref{wxControl}{wxcontrol}
@@ -28,6 +32,7 @@ QuickTime backend.
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
\membersection{Rendering media}\label{renderingmediawxmediactrl} \membersection{Rendering media}\label{renderingmediawxmediactrl}
Depending upon the backend, wxMediaCtrl can render Depending upon the backend, wxMediaCtrl can render
@@ -48,6 +53,7 @@ capabilities of the backend. For example, QuickTime cannot set
the playback rate of certain streaming media - while DirectShow is the playback rate of certain streaming media - while DirectShow is
slightly more flexible in that regard. slightly more flexible in that regard.
\membersection{Operation}\label{operationwxmediactrl} \membersection{Operation}\label{operationwxmediactrl}
When wxMediaCtrl plays a file, it plays until the stop position When wxMediaCtrl plays a file, it plays until the stop position
@@ -86,6 +92,50 @@ because some streams are not seekable, and when stop is called
on them they return to the beginning, thus wxMediaCtrl tries on them they return to the beginning, thus wxMediaCtrl tries
to keep consistant for all types of media. to keep consistant for all types of media.
Note that when changing the state of the media through Play()
and other methods, the media may not actually be in the
wxMEDIASTATE\_PLAYING, for example. If you are relying on the
media being in certain state catch the event relevant to the state.
See \helpref{wxMediaEvent}{wxmediaevent} for the kinds of events
that you can catch.
\membersection{Video size}\label{videosizewxmediactrl}
By default, wxMediaCtrl will scale the size of the video to the
requested amount passed to either it's constructor or Create().
After calling Load or performing an equivilant operation, you
can subsequently obtain the "real" size of the video (if there
is any) by calling GetBestSize(). Note that the actual result
on the display will be slightly different when ShowPlayerControls
is activated and the actual video size will be less then
specified due to the extra controls provided by the native toolkit.
In addition, the backend may modify GetBestSize() to include the
size of the extra controls - so if you want the real size of the
video just disable ShowPlayerControls().
The idea with setting GetBestSize to the size of the video is
that GetBestSize is a wxWindow-derived function that is called
when sizers on a window recalculate. What this means is that
if you use sizers by default the video will show in it's
original size without any extra assistance needed from the user.
\membersection{Player controls}\label{playercontrolswxmediactrl}
Normally, when you use wxMediaCtrl it is just a window for the video to
play in. However, some toolkits have their own media player interface.
For example, QuickTime generally has a bar below the video with a slider.
A special feature available to wxMediaCtrl, you can use the toolkit's interface instead of
making your own by using the \helpref{ShowPlayerControls()}{wxmediactrlshowplayercontrols}
function. There are several options for the flags parameter, with
the two general flags being wxMEDIACTRLPLAYERCONTROLS\_NONE which turns off
the native interface, and wxMEDIACTRLPLAYERCONTROLS\_DEFAULT which lets
wxMediaCtrl decide what native controls on the interface. Be sure to review
the caveats outlined in \helpref{Video size}{videosizewxmediactrl} before
doing so.
\membersection{Choosing a backend}\label{choosingbackendwxmediactrl} \membersection{Choosing a backend}\label{choosingbackendwxmediactrl}
Generally, you should almost certainly leave this part up to Generally, you should almost certainly leave this part up to
@@ -99,17 +149,48 @@ The following are valid backend identifiers -
\twocolwidtha{7cm} \twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt \begin{twocollist}\itemsep=0pt
\twocolitem{{\bf wxMEDIABACKEND\_DIRECTSHOW}}{ \twocolitem{{\bf wxMEDIABACKEND\_DIRECTSHOW}}{
Use ActiveMovie/DirectShow. Requires wxUSE\_DIRECTSHOW to be Use ActiveMovie/DirectShow. Uses the native ActiveMovie
enabled, requires linkage with the static library strmiids.lib, (I.E. DirectShow) control. Default backend on Windows and
and is available on Windows Only.} supported by nearly all Windows versions, even some
Windows CE versions. May display a windows media player
logo while inactive. }
\twocolitem{{\bf wxMEDIABACKEND\_QUICKTIME}}{ \twocolitem{{\bf wxMEDIABACKEND\_QUICKTIME}}{
Use QuickTime. Windows and Mac Only. NOTE: On Mac Systems lower than OSX 10.2 this defaults to emulating window positioning and suffers from several bugs, including not working correctly embedded in a wxNotebook. } Use QuickTime. Mac Only.
\twocolitem{{\bf wxMEDIABACKEND\_MCI}}{ WARNING: May not working correctly embedded in a wxNotebook.
Use Media Command Interface. Windows Only. } }
\twocolitem{{\bf wxMEDIABACKEND\_GSTREAMER}}{ \twocolitem{{\bf wxMEDIABACKEND\_GSTREAMER}}{
Use GStreamer. Unix Only. } Use GStreamer. Unix Only. Requires GStreamer 0.8 along
with at the very least the xvimagesink, xoverlay, and
gst-play modules of gstreamer to function. You need the correct
modules to play the relavant files, for example the mad module
to play mp3s, etc.}
\twocolitem{{\bf wxMEDIABACKEND\_WMP10}}{
Uses Windows Media Player 10 (Windows only) - works on mobile
machines with Windows Media Player 10 and desktop machines with
either Windows Media Player 9 or 10
}
\end{twocollist} \end{twocollist}
Note that other backends such as wxMEDIABACKEND\_MCI can now be
found at wxCode.
\membersection{Creating a backend}\label{creatingabackendwxmediactrl}
Creating a backend for wxMediaCtrl is a rather simple process. Simply derive
from wxMediaBackendCommonBase and implement the methods you want. The methods
in wxMediaBackend correspond to those in wxMediaCtrl except for CreateControl
which does the actual creation of the control, in cases where a custom control
is not needed you may simply call wxControl::Create.
You need to make sure to use the DECLARE\_CLASS and IMPLEMENT\_CLASS macros.
The only real tricky part is that you need to make sure the file in compiled
in, which if there are just backends in there will not happen and you may need
to use a force link hack (see http://www.wxwidgets.org/wiki/index.php/RTTI).
This is a rather simple example of how to create a backend in the
\helpref{wxActiveXContainer}{wxactivexcontainer} documentation.
\membersection{wxMediaCtrl::wxMediaCtrl}\label{wxmediactrlwxmediactrl} \membersection{wxMediaCtrl::wxMediaCtrl}\label{wxmediactrlwxmediactrl}
\func{}{wxMediaCtrl}{\void} \func{}{wxMediaCtrl}{\void}
@@ -173,25 +254,38 @@ wxMediaCtrl figure it out.}
\docparam{name}{Window name.} \docparam{name}{Window name.}
\membersection{wxMediaCtrl::Length}\label{wxmediactrlgetduration} \membersection{wxMediaCtrl::GetBestSize}\label{wxmediactrlgetbestsize}
\func{wxFileOffset}{GetDuration}{\void} \func{wxSize}{GetBestSize}{\void}
Obtains the length - the total amount of time the movie has in milliseconds. Obtains the best size relative to the original/natural size of the
video, if there is any. See \helpref{Video size}{videosizewxmediactrl}
for more information.
\membersection{wxMediaCtrl::Tell}\label{wxmediactrlgetposition} \membersection{wxMediaCtrl::GetPlaybackRate}\label{wxmediactrlgetplaybackrate}
\func{wxFileOffset}{GetPosition}{\void} \func{double}{GetPlaybackrate}{\void}
Obtains the current position in time within the movie in milliseconds. Obtains the playback rate, or speed of the media. \tt{1.0} represents normal
speed, while \tt{2.0} represents twice the normal speed of the media, for
example. Not supported on the GStreamer (Unix) backend.
Returns 0 on failure.
\membersection{wxMediaCtrl::GetVolume}\label{wxmediactrlgetvolume}
\func{double}{GetVolume}{\void}
Gets the volume of the media from a 0.0 to 1.0 range. Note that due to rounding
and other errors this may not be the exact value sent to SetVolume.
\membersection{wxMediaCtrl::GetState}\label{wxmediactrlgetstate} \membersection{wxMediaCtrl::GetState}\label{wxmediactrlgetstate}
\func{wxMediaCtrlState}{GetState}{\void} \func{wxMediaCtrlState}{GetState}{\void}
Obtains the state the playback of the movie is in - Obtains the state the playback of the media is in -
\twocolwidtha{7cm} \twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt \begin{twocollist}\itemsep=0pt
@@ -201,6 +295,13 @@ Obtains the state the playback of the movie is in -
\end{twocollist} \end{twocollist}
\membersection{wxMediaCtrl::Length}\label{wxmediactrllength}
\func{wxFileOffset}{Length}{\void}
Obtains the length - the total amount of time the movie has in milliseconds.
\membersection{wxMediaCtrl::Load}\label{wxmediactrlload} \membersection{wxMediaCtrl::Load}\label{wxmediactrlload}
\func{bool}{Load}{\param{const wxString\& }{fileName}} \func{bool}{Load}{\param{const wxString\& }{fileName}}
@@ -210,9 +311,31 @@ Loads the file that \tt{fileName} refers to. Returns false if loading fails.
\membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduri} \membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduri}
\func{bool}{Load}{\param{const wxURI\& }{location}} \func{bool}{Load}{\param{const wxURI\& }{uri}}
Loads the location that \tt{uri} refers to. Note that this is very implementation-dependant, although HTTP URI/URLs are generally supported, for example. Returns false if loading fails.
\membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduriwithproxy}
\func{bool}{Load}{\param{const wxURI\& }{uri}, \param{const wxURI\& }{proxy}}
Loads the location that \tt{uri} refers to with the proxy \tt{proxy}. Not implemented on most backends so it should be called with caution. Returns false if loading fails.
\membersection{wxMediaCtrl::LoadURI}\label{wxmediactrlloaduriliteral}
\func{bool}{LoadURI}{\param{const wxURI\& }{uri}}
Same as \helpref{Load}{wxmediactrlloaduri}. Kept for wxPython compatability.
\membersection{wxMediaCtrl::LoadURIWithProxy}\label{wxmediactrlloaduriwithproxyliteral}
\func{bool}{LoadURIWithProxy}{\param{const wxURI\& }{uri}, \param{const wxURI\& }{proxy}}
Same as \helpref{Load}{wxmediactrlloaduriwithproxy}. Kept for wxPython compatability.
Loads the url that \tt{location} refers to. Returns false if loading fails.
\membersection{wxMediaCtrl::Pause}\label{wxmediactrlpause} \membersection{wxMediaCtrl::Pause}\label{wxmediactrlpause}
@@ -235,54 +358,65 @@ Resumes playback of the movie.
Seeks to a position within the movie. Seeks to a position within the movie.
\membersection{wxMediaCtrl::Stop}\label{wxmediactrlstop} \membersection{wxMediaCtrl::SetPlaybackRate}\label{wxmediactrlsetplaybackrate}
\func{bool}{Stop}{\void} \func{bool}{SetPlaybackRate}{\param{double }{dRate}}
Stops the media. Sets the playback rate, or speed of the media, to that referred by \tt{dRate}.
\tt{1.0} represents normal speed, while \tt{2.0} represents twice the normal
See \helpref{Operation}{operationwxmediactrl} for an overview of how stopping works. speed of the media, for example. Not supported on the GStreamer (Unix) backend.
Returns true if successful.
\membersection{wxMediaCtrl::SetVolume}\label{wxmediactrlsetvolume} \membersection{wxMediaCtrl::SetVolume}\label{wxmediactrlsetvolume}
\func{bool}{SetVolume}{\param{double }{dVolume}} \func{bool}{SetVolume}{\param{double }{dVolume}}
Sets the volume of the media from a 0.0 to 1.0 range. Sets the volume of the media from a 0.0 to 1.0 range to that referred
by \tt{dVolume}. \tt{1.0} represents full volume, while \tt{0.5}
represents half (50 percent) volume, for example. Note that this may not be
\membersection{wxMediaCtrl::GetVolume}\label{wxmediactrlgetvolume} exact due to conversion and rounding errors, although setting the volume to
full or none is always exact. Returns true if successful.
\func{double}{GetVolume}{\void}
Gets the volume of the media from a 0.0 to 1.0 range.
\membersection{wxMediaCtrl::GetPlaybackRate}\label{wxmediactrlgetplaybackrate}
\func{double}{GetPlaybackrate}{\void}
Gets the playback rate of the media; for example 2.0 is double speed.
Not implemented on MCI or GStreamer.
\membersection{wxMediaCtrl::SetPlaybackRate}\label{wxmediactrlsetplaybackrate}
\func{bool}{SetPlaybackrate}{\param{double }{dVolume}}
Sets the rate that the media plays; for example 0.5 is half speed.
\membersection{wxMediaCtrl::ShowPlayerControls}\label{wxmediactrlshowplayercontrols} \membersection{wxMediaCtrl::ShowPlayerControls}\label{wxmediactrlshowplayercontrols}
\func{bool}{ShowPlayerControls}{\param{wxMediaCtrlPlayerControls }{flags}} \func{bool}{ShowPlayerControls}{\param{wxMediaCtrlPlayerControls }{flags = wxMEDIACTRLPLAYERCONTROLS\_DEFAULT}}
Normally, when you use wxMediaCtrl it is just a window for the video to A special feature to wxMediaCtrl. Applications using native toolkits such as
play in. However, platforms generally have their own media player interface, QuickTime usually have a scrollbar, play button, and more provided to
like quicktime has a bar below the video with a slider etc.. If you want that native them by the toolkit. By default wxMediaCtrl does not do this. However, on
interface instead of making your own use this function. There are several options the directshow and quicktime backends you can show or hide the native controls
for the flags parameter, however you can look at the mediactrl header for these. provided by the underlying toolkit at will using ShowPlayerControls. Simply
The two general flags are wxMEDIACTRLPLAYERCONTROLS\_NONE which turns off the calling the function with default parameters tells wxMediaCtrl to use the
native interface, and wxMEDIACTRLPLAYERCONTROLS\_DEFAULT which lets wxMediaCtrl default controls provided by the toolkit. The function takes a
decide what native controls on the interface. \tt{wxMediaCtrlPlayerControls} enumeration as follows:
\twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt
\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_NONE}}{No controls. return wxMediaCtrl to it's default state.}
\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_STEP}}{Step controls like fastfoward, step one frame etc.}
\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_VOLUME}}{Volume controls like the speaker icon, volume slider, etc.}
\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_DEFAULT}}{Default controls for the toolkit. Currently a typedef for wxMEDIACTRLPLAYERCONTROLS\_STEP and wxMEDIACTRLPLAYERCONTROLS\_VOLUME.}
\end{twocollist}
For more see \helpref{Player controls}{playercontrolswxmediactrl}. Currently
only implemented on the QuickTime and DirectShow backends. The function
returns true on success.
\membersection{wxMediaCtrl::Stop}\label{wxmediactrlstop}
\func{bool}{Stop}{\void}
Stops the media.
See \helpref{Operation}{operationwxmediactrl} for an overview of how
stopping works.
\membersection{wxMediaCtrl::Tell}\label{wxmediactrlgetposition}
\func{wxFileOffset}{Tell}{\void}
Obtains the current position in time within the movie in milliseconds.

View File

@@ -25,10 +25,26 @@ Event \helpref{wxMediaCtrl}{wxmediactrl} uses.
\twocolwidtha{7cm} \twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt \begin{twocollist}\itemsep=0pt
\twocolitem{{\bf EVT\_MEDIA\_LOADED(func)}}{Sent when a media has loaded enough data that it can start playing.} \twocolitem{{\bf EVT\_MEDIA\_LOADED(func)}}{
Sent when a media has loaded enough data that it can start playing.}
\twocolitem{{\bf EVT\_MEDIA\_STOP(func)}}{ \twocolitem{{\bf EVT\_MEDIA\_STOP(func)}}{
Triggerred right before the media stops. You can Veto this event to prevent it from stopping, causing it to continue playing - even if it has reached that end of the media. } Send when a media has switched to the wxMEDIASTATE\_STOPPED state.
\twocolitem{{\bf EVT\_MEDIA\_FINISHED(func)}}{Sent when a media has finished playing in a \helpref{wxMediaCtrl}{wxmediactrl}. Note that if you connect to this event and don't skip it, it will override the looping behaviour of the media control.} You may be able to Veto this event to prevent it from stopping,
causing it to continue playing - even if it has reached that end of the media
(note that this may not have the desired effect - if you want to loop the
media, for example, catch the EVT\_MEDIA\_FINISHED and play there instead). }
\twocolitem{{\bf EVT\_MEDIA\_FINISHED(func)}}{
Sent when a media has finished playing in a \helpref{wxMediaCtrl}{wxmediactrl}.
}
\twocolitem{{\bf EVT\_MEDIA\_STATECHANGED(func)}}{
Send when a media has switched its state (from any media state).
}
\twocolitem{{\bf EVT\_MEDIA\_PLAY(func)}}{
Send when a media has switched to the wxMEDIASTATE\_PLAYING state.
}
\twocolitem{{\bf EVT\_MEDIA\_PAUSE(func)}}{
Send when a media has switched to the wxMEDIASTATE\_PAUSED state.
}
\end{twocollist} \end{twocollist}
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}

View File

@@ -22,6 +22,9 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Pre-compiled header stuff // Pre-compiled header stuff
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma interface "mediactrl.h"
#endif
#include "wx/defs.h" #include "wx/defs.h"
@@ -71,7 +74,8 @@ enum wxMediaCtrlPlayerControls
#define wxMEDIABACKEND_MCI wxT("wxMCIMediaBackend") #define wxMEDIABACKEND_MCI wxT("wxMCIMediaBackend")
#define wxMEDIABACKEND_QUICKTIME wxT("wxQTMediaBackend") #define wxMEDIABACKEND_QUICKTIME wxT("wxQTMediaBackend")
#define wxMEDIABACKEND_GSTREAMER wxT("wxGStreamerMediaBackend") #define wxMEDIABACKEND_GSTREAMER wxT("wxGStreamerMediaBackend")
#define wxMEDIABACKEND_REALPLAYER wxT("wxRealPlayerMediaBackend")
#define wxMEDIABACKEND_WMP10 wxT("wxWMP10MediaBackend")
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// //
@@ -190,14 +194,17 @@ public:
wxFileOffset Tell(); //FIXME: This should be const wxFileOffset Tell(); //FIXME: This should be const
wxFileOffset Length(); //FIXME: This should be const wxFileOffset Length(); //FIXME: This should be const
#if wxABI_VERSION >= 20601 /* 2.6.1+ only */
double GetPlaybackRate(); //All but MCI & GStreamer double GetPlaybackRate(); //All but MCI & GStreamer
bool SetPlaybackRate(double dRate); //All but MCI & GStreamer bool SetPlaybackRate(double dRate); //All but MCI & GStreamer
#endif
#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
bool Load(const wxURI& location); bool Load(const wxURI& location);
bool Load(const wxURI& location, const wxURI& proxy); bool Load(const wxURI& location, const wxURI& proxy);
wxFileOffset GetDownloadProgress(); wxFileOffset GetDownloadProgress(); // DirectShow only
wxFileOffset GetDownloadTotal(); wxFileOffset GetDownloadTotal(); // DirectShow only
double GetVolume(); double GetVolume();
bool SetVolume(double dVolume); bool SetVolume(double dVolume);
@@ -210,7 +217,7 @@ public:
{ return Load(wxURI(fileName)); } { return Load(wxURI(fileName)); }
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy) bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
{ return Load(wxURI(fileName), wxURI(proxy)); } { return Load(wxURI(fileName), wxURI(proxy)); }
#endif
protected: protected:
static wxClassInfo* NextBackend(); static wxClassInfo* NextBackend();
@@ -324,12 +331,10 @@ public:
//Event ID to give to our events //Event ID to give to our events
#define wxMEDIA_FINISHED_ID 13000 #define wxMEDIA_FINISHED_ID 13000
#define wxMEDIA_STOP_ID 13001 #define wxMEDIA_STOP_ID 13001
#define wxMEDIA_LOADED_ID 13002
//Define our event types - we need to call DEFINE_EVENT_TYPE(EVT) later //Define our event types - we need to call DEFINE_EVENT_TYPE(EVT) later
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STOP, wxMEDIA_STOP_ID) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STOP, wxMEDIA_STOP_ID)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_LOADED, wxMEDIA_LOADED_ID)
//Function type(s) our events need //Function type(s) our events need
typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&); typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
@@ -340,7 +345,24 @@ typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
//Macro for usage with message maps //Macro for usage with message maps
#define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ), #define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#define EVT_MEDIA_STOP(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STOP, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ), #define EVT_MEDIA_STOP(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STOP, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
# define wxMEDIA_LOADED_ID 13002
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_LOADED, wxMEDIA_LOADED_ID)
# define EVT_MEDIA_LOADED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_LOADED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ), # define EVT_MEDIA_LOADED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_LOADED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#endif
#if wxABI_VERSION >= 20603 /* 2.6.3+ only */
# define wxMEDIA_STATECHANGED_ID 13003
# define wxMEDIA_PLAY_ID 13004
# define wxMEDIA_PAUSE_ID 13005
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STATECHANGED, wxMEDIA_STATECHANGED_ID)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_PLAY, wxMEDIA_PLAY_ID)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_PAUSE, wxMEDIA_PAUSE_ID)
# define EVT_MEDIA_STATECHANGED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STATECHANGED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
# define EVT_MEDIA_PLAY(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_PLAY, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
# define EVT_MEDIA_PAUSE(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_PAUSE, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// common backend base class used by many other backends // common backend base class used by many other backends
@@ -353,11 +375,26 @@ public:
void QueueEvent(wxEventType evtType); void QueueEvent(wxEventType evtType);
// notify that the movie playback is finished // notify that the movie playback is finished
void QueueFinishEvent() { QueueEvent(wxEVT_MEDIA_FINISHED); } void QueueFinishEvent()
{
#if wxABI_VERSION >= 20603 /* 2.6.3+ only */
QueueEvent(wxEVT_MEDIA_STATECHANGED);
#endif
QueueEvent(wxEVT_MEDIA_FINISHED);
}
// send the stop event and return true if it hasn't been vetoed // send the stop event and return true if it hasn't been vetoed
bool SendStopEvent(); bool SendStopEvent();
// Queue pause event
void QueuePlayEvent();
// Queue pause event
void QueuePauseEvent();
// Queue stop event (no veto)
void QueueStopEvent();
protected: protected:
// call this when the movie size has changed but not because it has just // call this when the movie size has changed but not because it has just
// been loaded (in this case, call NotifyMovieLoaded() below) // been loaded (in this case, call NotifyMovieLoaded() below)

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/ole/activex.h // Name: wx/activex.h
// Purpose: wxActiveXContainer class // Purpose: wxActiveXContainer class
// Author: Ryan Norton <wxprojects@comcast.net> // Author: Ryan Norton <wxprojects@comcast.net>
// Modified by: // Modified by:
@@ -42,6 +42,7 @@
// WX includes // WX includes
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "wx/window.h" #include "wx/window.h"
#include "wx/variant.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// MSW COM includes // MSW COM includes
@@ -150,10 +151,6 @@ WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceObject, IOleInPlaceObject)
WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceActiveObject, IOleInPlaceActiveObject) WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceActiveObject, IOleInPlaceActiveObject)
WX_DECLARE_AUTOOLE(wxAutoIOleDocumentView, IOleDocumentView) WX_DECLARE_AUTOOLE(wxAutoIOleDocumentView, IOleDocumentView)
WX_DECLARE_AUTOOLE(wxAutoIViewObject, IViewObject) WX_DECLARE_AUTOOLE(wxAutoIViewObject, IViewObject)
WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
class wxActiveXContainer : public wxWindow class wxActiveXContainer : public wxWindow
{ {
@@ -168,6 +165,7 @@ public:
protected: protected:
friend class FrameSite; friend class FrameSite;
friend class wxActiveXEvents;
wxAutoIDispatch m_Dispatch; wxAutoIDispatch m_Dispatch;
wxAutoIOleClientSite m_clientSite; wxAutoIOleClientSite m_clientSite;
@@ -185,4 +183,50 @@ protected:
void CreateActiveX(REFIID, IUnknown*); void CreateActiveX(REFIID, IUnknown*);
}; };
// Events
class wxActiveXEvent : public wxCommandEvent
{
private:
friend class wxActiveXEvents;
wxVariant m_params;
DISPID m_dispid;
public:
virtual wxEvent *Clone() const
{ return new wxActiveXEvent(*this); }
int ParamCount() const
{ return m_params.GetCount(); }
wxString ParamType(int idx) const
{
wxASSERT(idx >= 0 && idx < m_params.GetCount());
return m_params[idx].GetType();
}
wxString ParamName(int idx) const
{
wxASSERT(idx >= 0 && idx < m_params.GetCount());
return m_params[idx].GetName();
}
wxVariant& operator[] (int idx)
{
wxASSERT(idx >= 0 && idx < ParamCount());
return m_params[idx];
}
DISPID GetDispatchId() const
{ return m_dispid; }
};
#define wxACTIVEX_ID 14001
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_ACTIVEX, wxACTIVEX_ID)
typedef void (wxEvtHandler::*wxActiveXEventFunction)(wxActiveXEvent&);
#define EVT_ACTIVEX(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_ACTIVEX, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
#define wxActiveXEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxActiveXEventFunction, &func)
#endif // _WX_MSW_OLE_ACTIVEXCONTAINER_H_ #endif // _WX_MSW_OLE_ACTIVEXCONTAINER_H_

View File

@@ -29,11 +29,7 @@
// 1) Certain backends can't play the same media file at the same time (MCI, // 1) Certain backends can't play the same media file at the same time (MCI,
// Cocoa NSMovieView-Quicktime). // Cocoa NSMovieView-Quicktime).
// 2) Positioning on Mac Carbon is messed up if put in a sub-control like a // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
// Notebook (like this sample does) on OS versions < 10.2. // Notebook (like this sample does).
// 3) On unix the video may not work - it only checks for a few video
// sinks - xvimagesink, ximagesink and whatever gnome preferences has -
// if gnome preferences is not available or you have a different video
// sink then those two (such as sdlvideosink) then you'll get black video
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ============================================================================ // ============================================================================
@@ -116,6 +112,8 @@ enum
// wxID_EXIT, [built-in to wxWidgets] // wxID_EXIT, [built-in to wxWidgets]
// Control event IDs // Control event IDs
wxID_SLIDER, wxID_SLIDER,
wxID_PBSLIDER,
wxID_VOLSLIDER,
wxID_NOTEBOOK, wxID_NOTEBOOK,
wxID_MEDIACTRL, wxID_MEDIACTRL,
wxID_BUTTONNEXT, wxID_BUTTONNEXT,
@@ -179,9 +177,6 @@ public:
void OnSelectBackend(wxCommandEvent& event); void OnSelectBackend(wxCommandEvent& event);
// Notebook event handlers
void OnPageChange(wxNotebookEvent& event);
// Key event handlers // Key event handlers
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
@@ -198,9 +193,6 @@ public:
void OnClose(wxCloseEvent& event); void OnClose(wxCloseEvent& event);
private: private:
// Rebuild base status string (see Implementation)
void ResetStatus();
// Common open file code // Common open file code
void OpenFile(bool bNewPage); void OpenFile(bool bNewPage);
void OpenURL(bool bNewPage); void OpenURL(bool bNewPage);
@@ -208,7 +200,6 @@ private:
void DoPlayFile(const wxString& path); void DoPlayFile(const wxString& path);
class wxMediaPlayerTimer* m_timer; //Timer to write info to status bar class wxMediaPlayerTimer* m_timer; //Timer to write info to status bar
wxString m_basestatus; //Base status string (see ResetStatus())
wxNotebook* m_notebook; //Notebook containing our pages wxNotebook* m_notebook; //Notebook containing our pages
// Maybe I should use more accessors, but for simplicity // Maybe I should use more accessors, but for simplicity
@@ -232,8 +223,13 @@ class wxMediaPlayerNotebookPage : public wxPanel
// Slider event handlers // Slider event handlers
void OnBeginSeek(wxScrollEvent& event); void OnBeginSeek(wxScrollEvent& event);
void OnEndSeek(wxScrollEvent& event); void OnEndSeek(wxScrollEvent& event);
void OnPBChange(wxScrollEvent& event);
void OnVolChange(wxScrollEvent& event);
// Media event handlers // Media event handlers
void OnMediaPlay(wxMediaEvent& event);
void OnMediaPause(wxMediaEvent& event);
void OnMediaStop(wxMediaEvent& event);
void OnMediaFinished(wxMediaEvent& event); void OnMediaFinished(wxMediaEvent& event);
public: public:
@@ -248,6 +244,8 @@ public:
wxMediaCtrl* m_mediactrl; //Our media control wxMediaCtrl* m_mediactrl; //Our media control
class wxMediaPlayerListCtrl* m_playlist; //Our playlist class wxMediaPlayerListCtrl* m_playlist; //Our playlist
wxSlider* m_slider; //The slider below our media control wxSlider* m_slider; //The slider below our media control
wxSlider* m_pbSlider; //Lower-left slider for adjusting speed
wxSlider* m_volSlider; //Lower-right slider for adjusting volume
int m_nLoops; //Number of times media has looped int m_nLoops; //Number of times media has looped
bool m_bLoop; //Whether we are looping or not bool m_bLoop; //Whether we are looping or not
bool m_bIsBeingDragged; //Whether the user is dragging the scroll bar bool m_bIsBeingDragged; //Whether the user is dragging the scroll bar
@@ -411,6 +409,9 @@ IMPLEMENT_APP(wxMediaPlayerApp)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxMediaPlayerApp::OnInit() bool wxMediaPlayerApp::OnInit()
{ {
// SetAppName() lets wxConfig and others know where to write
SetAppName(wxT("wxMediaPlayer"));
wxMediaPlayerFrame *frame = wxMediaPlayerFrame *frame =
new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample")); new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
frame->Show(true); frame->Show(true);
@@ -440,8 +441,8 @@ bool wxMediaPlayerApp::OnInit()
{ {
frame->AddToPlayList((parser.GetParam (paramNr))); frame->AddToPlayList((parser.GetParam (paramNr)));
} }
wxCommandEvent emptyevt; wxCommandEvent theEvent(wxEVT_COMMAND_MENU_SELECTED, wxID_NEXT);
frame->OnNext(emptyevt); frame->AddPendingEvent(theEvent);
} }
#endif #endif
@@ -660,12 +661,6 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED, this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend)); wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
//
// Notebook events
//
this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
wxNotebookEventHandler(wxMediaPlayerFrame::OnPageChange));
// //
// Key events // Key events
// //
@@ -702,13 +697,13 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
// it properly loads the playlist for each page without // it properly loads the playlist for each page without
// conflicting (loading the same data) with the other ones. // conflicting (loading the same data) with the other ones.
// //
wxConfigBase* conf = wxConfigBase::Get(); wxConfig conf;
wxString key, outstring; wxString key, outstring;
for(int i = 0; ; ++i) for(int i = 0; ; ++i)
{ {
key.clear(); key.clear();
key << i; key << i;
if(!conf->Read(key, &outstring)) if(!conf.Read(key, &outstring))
break; break;
page->m_playlist->AddToPlayList(outstring); page->m_playlist->AddToPlayList(outstring);
} }
@@ -717,7 +712,7 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
// Create a timer to update our status bar // Create a timer to update our status bar
// //
m_timer = new wxMediaPlayerTimer(this); m_timer = new wxMediaPlayerTimer(this);
m_timer->Start(100); m_timer->Start(500);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -728,6 +723,9 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxMediaPlayerFrame::~wxMediaPlayerFrame() wxMediaPlayerFrame::~wxMediaPlayerFrame()
{ {
// Shut down our timer
delete m_timer;
// //
// Here we save our info to the registry or whatever // Here we save our info to the registry or whatever
// mechanism the OS uses. // mechanism the OS uses.
@@ -751,19 +749,17 @@ wxMediaPlayerFrame::~wxMediaPlayerFrame()
wxMediaPlayerListCtrl* playlist = wxMediaPlayerListCtrl* playlist =
((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist; ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
wxConfigBase* conf = wxConfigBase::Get(); wxConfig conf;
conf->DeleteAll(); conf.DeleteAll();
for(int i = 0; i < playlist->GetItemCount(); ++i) for(int i = 0; i < playlist->GetItemCount(); ++i)
{ {
wxString* pData = (wxString*) playlist->GetItemData(i); wxString* pData = (wxString*) playlist->GetItemData(i);
wxString s; wxString s;
s << i; s << i;
conf->Write(s, *(pData)); conf.Write(s, *(pData));
delete pData; delete pData;
} }
delete m_timer;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -785,38 +781,6 @@ void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
currentpage->m_playlist->AddToPlayList(szString); currentpage->m_playlist->AddToPlayList(szString);
} }
// ----------------------------------------------------------------------------
// wxMediaPlayerFrame::ResetStatus
//
// Here we just make a simple status string with some useful info about
// the media that we won't change later - such as the length of the media.
//
// We then append some other info that changes in wxMediaPlayerTimer::Notify, then
// set the status bar to this text.
//
// In real applications, you'd want to find a better way to do this,
// such as static text controls (wxStaticText).
//
// We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
// we divide by 1000).
//
// We also reset our loop counter here.
// ----------------------------------------------------------------------------
void wxMediaPlayerFrame::ResetStatus()
{
wxMediaCtrl* currentMediaCtrl =
((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_mediactrl;
m_basestatus = wxString::Format(wxT("Size(x,y):%i,%i ")
wxT("Length(Seconds):%u Speed:%1.1fx"),
currentMediaCtrl->GetBestSize().x,
currentMediaCtrl->GetBestSize().y,
(unsigned)((currentMediaCtrl->Length() / 1000)),
currentMediaCtrl->GetPlaybackRate()
);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMediaPlayerFrame::OnQuit // wxMediaPlayerFrame::OnQuit
// //
@@ -838,10 +802,25 @@ void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{ {
wxString msg; wxString msg;
msg.Printf( wxT("This is a test of wxMediaCtrl.\n") msg.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
wxT("Welcome to %s"), wxVERSION_STRING);
wxMessageBox(msg, wxT("About wxMediaCtrl test"), wxOK | wxICON_INFORMATION, this); wxT("Intructions:\n")
wxT("The top slider shows the current the current position, ")
wxT("which you can change by dragging and releasing it.\n")
wxT("The gauge (progress bar) shows the progress in ")
wxT("downloading data of the current file - it may always be ")
wxT("Empty due to lack of support from the current backend.\n")
wxT("The lower-left slider controls the volume and the lower-")
wxT("right slider controls the playback rate/speed of the ")
wxT("media\n\n")
wxT("Currently using: %s"), wxVERSION_STRING);
wxMessageBox(msg, wxT("About wxMediaCtrl test"),
wxOK | wxICON_INFORMATION, this);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -995,17 +974,11 @@ void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
{ {
if( !currentpage->m_mediactrl->Pause() ) if( !currentpage->m_mediactrl->Pause() )
wxMessageBox(wxT("Couldn't pause movie!")); wxMessageBox(wxT("Couldn't pause movie!"));
else
currentpage->m_playlist->SetItem(
currentpage->m_nLastFileId, 0, wxT("||"));
} }
else else
{ {
if( !currentpage->m_mediactrl->Play() ) if( !currentpage->m_mediactrl->Play() )
wxMessageBox(wxT("Couldn't play movie!")); wxMessageBox(wxT("Couldn't play movie!"));
else
currentpage->m_playlist->SetItem(
currentpage->m_nLastFileId, 0, wxT(">"));
} }
} }
else else
@@ -1075,18 +1048,9 @@ void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">")); currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
} }
currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
2, wxString::Format(wxT("%u"),
(unsigned) currentpage->m_mediactrl->Length() / 1000)
);
ResetStatus();
currentpage->m_slider->SetRange(0,
(int)(currentpage->m_mediactrl->Length() / 1000));
currentpage->m_gauge->SetRange((int)(currentpage->m_mediactrl->Length() / 1000));
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMediaPlayerFrame::OnSelectBackend // wxMediaPlayerFrame::OnSelectBackend
// //
@@ -1408,7 +1372,7 @@ void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMediaPlayerFrame::OnVolumeDown // wxMediaPlayerFrame::OnVolumeDown
// //
// Lowers the volume of the media control by 10% // Lowers the volume of the media control by 5%
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event)) void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
{ {
@@ -1416,13 +1380,13 @@ void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
(wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage(); (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
double dVolume = currentpage->m_mediactrl->GetVolume(); double dVolume = currentpage->m_mediactrl->GetVolume();
currentpage->m_mediactrl->SetVolume(dVolume < 0.1 ? 0.0 : dVolume - .1); currentpage->m_mediactrl->SetVolume(dVolume < 0.05 ? 0.0 : dVolume - .05);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMediaPlayerFrame::OnVolumeUp // wxMediaPlayerFrame::OnVolumeUp
// //
// Increases the volume of the media control by 10% // Increases the volume of the media control by 5%
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event)) void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
{ {
@@ -1430,17 +1394,7 @@ void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
(wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage(); (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
double dVolume = currentpage->m_mediactrl->GetVolume(); double dVolume = currentpage->m_mediactrl->GetVolume();
currentpage->m_mediactrl->SetVolume(dVolume > 0.9 ? 1.0 : dVolume + .1); currentpage->m_mediactrl->SetVolume(dVolume > 0.95 ? 1.0 : dVolume + .05);
}
// ----------------------------------------------------------------------------
// wxMediaPlayerFrame::OnPageChange
//
// Called when the user changes the current notebook page shown
// ----------------------------------------------------------------------------
void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
{
ResetStatus();
} }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -1452,42 +1406,94 @@ void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMediaPlayerTimer::Notify // wxMediaPlayerTimer::Notify
// //
// 1) Update our slider with the position were are in in the media // 1) Updates media information on the status bar
// 2) Update our status bar with the base text from wxMediaPlayerFrame::ResetStatus, // 2) Sets the max/min length of the slider and guage
// append some non-static (changing) info to it, then set the //
// status bar text to that result // Note that the reason we continually do this and don't cache it is because
// some backends such as GStreamer are dynamic change values all the time
// and often don't have things like duration or video size available
// until the media is actually being played
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxMediaPlayerTimer::Notify() void wxMediaPlayerTimer::Notify()
{ {
wxMediaPlayerNotebookPage* currentpage = wxMediaPlayerNotebookPage* currentpage =
(wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage(); (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
wxMediaCtrl* currentMediaCtrl = currentpage->m_mediactrl;
if(currentpage) if(currentpage)
{ {
// if the slider is being dragged then update it with the song position // Number of minutes/seconds total
wxLongLong llLength = currentpage->m_mediactrl->Length();
int nMinutes = (int) (llLength / 60000).GetValue();
int nSeconds = (int) ((llLength % 60000)/1000).GetValue();
// Duration string (i.e. MM:SS)
wxString sDuration;
sDuration.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
// Number of minutes/seconds total
wxLongLong llTell = currentpage->m_mediactrl->Tell();
nMinutes = (int) (llTell / 60000).GetValue();
nSeconds = (int) ((llTell % 60000)/1000).GetValue();
// Position string (i.e. MM:SS)
wxString sPosition;
sPosition.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
// Set the third item in the listctrl entry to the duration string
if(currentpage->m_nLastFileId >= 0)
currentpage->m_playlist->SetItem(
currentpage->m_nLastFileId, 2, sDuration);
// Setup the slider and gauge min/max values
currentpage->m_slider->SetRange(0, (int)(llLength / 1000).GetValue());
currentpage->m_gauge->SetRange(100);
// if the slider is not being dragged then update it with the song position
if(currentpage->IsBeingDragged() == false) if(currentpage->IsBeingDragged() == false)
currentpage->m_slider->SetValue((long)(llTell / 1000).GetValue());
// Update the gauge with the download progress
wxLongLong llDownloadProgress =
currentpage->m_mediactrl->GetDownloadProgress();
wxLongLong llDownloadTotal =
currentpage->m_mediactrl->GetDownloadTotal();
if(llDownloadTotal.GetValue() != 0)
{ {
long lPosition = (long)( currentpage->m_mediactrl->Tell() / 1000 ); currentpage->m_gauge->SetValue(
currentpage->m_slider->SetValue(lPosition); (int) ((llDownloadProgress * 100) / llDownloadTotal).GetValue()
);
} }
// update guage with value from slider // GetBestSize holds the original video size
currentpage->m_gauge->SetValue(currentpage->m_slider->GetValue()); wxSize videoSize = currentMediaCtrl->GetBestSize();
// Now the big part - set the status bar text to
// hold various metadata about the media
#if wxUSE_STATUSBAR #if wxUSE_STATUSBAR
m_frame->SetStatusText(wxString::Format( m_frame->SetStatusText(wxString::Format(
wxT("%s Pos:%u State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"), wxT("Size(x,y):%i,%i ")
m_frame->m_basestatus.c_str(), wxT("Position:%s/%s Speed:%1.1fx ")
currentpage->m_slider->GetValue(), wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
videoSize.x,
videoSize.y,
sPosition.c_str(),
sDuration.c_str(),
currentMediaCtrl->GetPlaybackRate(),
wxGetMediaStateText(currentpage->m_mediactrl->GetState()), wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
currentpage->m_nLoops, currentpage->m_nLoops,
(int)currentpage->m_mediactrl->GetDownloadProgress(), (int)llDownloadProgress.GetValue(),
(int)currentpage->m_mediactrl->GetDownloadTotal(), (int)llDownloadTotal.GetValue(),
(int)(currentpage->m_mediactrl->GetVolume() * 100))); (int)(currentpage->m_mediactrl->GetVolume() * 100)));
#endif // wxUSE_STATUSBAR #endif // wxUSE_STATUSBAR
} }
} }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// //
// wxMediaPlayerNotebookPage // wxMediaPlayerNotebookPage
@@ -1510,7 +1516,6 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
m_bIsBeingDragged(false), m_bIsBeingDragged(false),
m_parentFrame(parentFrame) m_parentFrame(parentFrame)
{ {
// //
// Layout // Layout
// //
@@ -1539,7 +1544,8 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString, bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
wxDefaultPosition, wxDefaultSize, 0, wxDefaultPosition, wxDefaultSize, 0,
//you could specify a macrod backend here like //you could specify a macrod backend here like
//wxMEDIABACKEND_QUICKTIME); // wxMEDIABACKEND_WMP10);
// wxT("wxPDFMediaBackend"));
szBackend); szBackend);
//you could change the cursor here like //you could change the cursor here like
// m_mediactrl->SetCursor(wxCURSOR_BLANK); // m_mediactrl->SetCursor(wxCURSOR_BLANK);
@@ -1571,8 +1577,8 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
// > - Currently Playing // > - Currently Playing
// [] - Stopped // [] - Stopped
// || - Paused // || - Paused
// (( - Volume Down 10% // (( - Volume Down 5%
// )) - Volume Up 10% // )) - Volume Up 5%
// //
// Column two is the name of the file // Column two is the name of the file
// //
@@ -1615,7 +1621,7 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
// //
@@ -1628,7 +1634,6 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
wxSL_HORIZONTAL ); wxSL_HORIZONTAL );
sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5); sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
// //
// Create the gauge // Create the gauge
// //
@@ -1637,6 +1642,26 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
wxGA_HORIZONTAL | wxGA_SMOOTH); wxGA_HORIZONTAL | wxGA_SMOOTH);
sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5); sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
//
// Create the speed/volume sliders
//
wxBoxSizer* horsizer3 = new wxBoxSizer(wxHORIZONTAL);
m_volSlider = new wxSlider(this, wxID_VOLSLIDER, 100, // init
0, // start
100, // end
wxDefaultPosition, wxSize(250,20),
wxSL_HORIZONTAL );
horsizer3->Add(m_volSlider, 1, wxALL, 5);
m_pbSlider = new wxSlider(this, wxID_PBSLIDER, 4, // init
1, // start
16, // end
wxDefaultPosition, wxSize(250,20),
wxSL_HORIZONTAL );
horsizer3->Add(m_pbSlider, 1, wxALL, 5);
sizer->Add(horsizer3, 1, wxCENTRE | wxALL, 5);
// //
// ListCtrl events // ListCtrl events
// //
@@ -1651,10 +1676,20 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek)); wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE, this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek)); wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
this->Connect(wxID_PBSLIDER, wxEVT_SCROLL_THUMBRELEASE,
wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange));
this->Connect(wxID_VOLSLIDER, wxEVT_SCROLL_THUMBRELEASE,
wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange));
// //
// Media Control events // Media Control events
// //
this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY,
wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PAUSE,
wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause));
this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop));
this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED, this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished)); wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED, this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
@@ -1724,9 +1759,67 @@ bool wxMediaPlayerNotebookPage::IsBeingDragged()
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// OnMediaFinished // wxMediaPlayerNotebookPage::OnVolChange
// //
// Called when the media stops playing. // Called when the user is done dragging the volume-changing slider
// ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent& WXUNUSED(event))
{
if( m_mediactrl->SetVolume(
m_volSlider->GetValue() / 100.0
) == false )
wxMessageBox(wxT("Couldn't set volume!"));
}
// ----------------------------------------------------------------------------
// wxMediaPlayerNotebookPage::OnPBChange
//
// Called when the user is done dragging the speed-changing slider
// ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent& WXUNUSED(event))
{
if( m_mediactrl->SetPlaybackRate(
m_pbSlider->GetValue() * .25
) == false )
wxMessageBox(wxT("Couldn't set playbackrate!"));
}
// ----------------------------------------------------------------------------
// wxMediaPlayerNotebookPage::OnMediaPlay
//
// Called when the media plays.
// ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent& WXUNUSED(event))
{
m_playlist->SetItem(m_nLastFileId, 0, wxT(">"));
}
// ----------------------------------------------------------------------------
// wxMediaPlayerNotebookPage::OnMediaPause
//
// Called when the media is paused.
// ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent& WXUNUSED(event))
{
m_playlist->SetItem(m_nLastFileId, 0, wxT("||"));
}
// ----------------------------------------------------------------------------
// wxMediaPlayerNotebookPage::OnMediaStop
//
// Called when the media stops.
// ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
{
m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
}
// ----------------------------------------------------------------------------
// wxMediaPlayerNotebookPage::OnMediaFinished
//
// Called when the media finishes playing.
// Here we loop it if the user wants to (has been selected from file menu) // Here we loop it if the user wants to (has been selected from file menu)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event)) void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))

View File

@@ -9,6 +9,8 @@
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// TODO: Platform specific backend defaults?
//=========================================================================== //===========================================================================
// Definitions // Definitions
//=========================================================================== //===========================================================================
@@ -17,6 +19,10 @@
// Pre-compiled header stuff // Pre-compiled header stuff
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "mediactrl.h"
#endif
#include "wx/wxprec.h" #include "wx/wxprec.h"
#ifdef __BORLANDC__ #ifdef __BORLANDC__
@@ -44,12 +50,15 @@
// RTTI and Event implementations // RTTI and Event implementations
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IMPLEMENT_CLASS(wxMediaCtrl, wxControl) IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
IMPLEMENT_CLASS(wxMediaBackend, wxObject) DEFINE_EVENT_TYPE(wxEVT_MEDIA_STATECHANGED)
IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent) DEFINE_EVENT_TYPE(wxEVT_MEDIA_PLAY)
DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED) DEFINE_EVENT_TYPE(wxEVT_MEDIA_PAUSE)
DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED) IMPLEMENT_CLASS(wxMediaBackend, wxObject);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP) IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// //
@@ -228,7 +237,7 @@ bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxMediaCtrl::NextBackend // wxMediaCtrl::NextBackend (static)
// //
// //
// Search through the RTTI hashmap one at a // Search through the RTTI hashmap one at a
@@ -239,8 +248,7 @@ bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
// STL isn't compatible with and will have a compilation error // STL isn't compatible with and will have a compilation error
// on a wxNode, however, wxHashTable::compatibility_iterator is // on a wxNode, however, wxHashTable::compatibility_iterator is
// incompatible with the old 2.4 stable version - but since // incompatible with the old 2.4 stable version - but since
// we're in 2.5 only we don't need to worry about this // we're in 2.5+ only we don't need to worry about the new version
// static
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
wxClassInfo* wxMediaCtrl::NextBackend() wxClassInfo* wxMediaCtrl::NextBackend()
{ {
@@ -507,9 +515,37 @@ void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
m_ctrl->AddPendingEvent(theEvent); m_ctrl->AddPendingEvent(theEvent);
} }
#include "wx/html/forcelnk.h" void wxMediaBackendCommonBase::QueuePlayEvent()
FORCE_LINK(basewxmediabackends) {
QueueEvent(wxEVT_MEDIA_STATECHANGED);
QueueEvent(wxEVT_MEDIA_PLAY);
}
void wxMediaBackendCommonBase::QueuePauseEvent()
{
QueueEvent(wxEVT_MEDIA_STATECHANGED);
QueueEvent(wxEVT_MEDIA_PAUSE);
}
void wxMediaBackendCommonBase::QueueStopEvent()
{
QueueEvent(wxEVT_MEDIA_STATECHANGED);
QueueEvent(wxEVT_MEDIA_STOP);
}
//
// Force link default backends in -
// see http://wiki.wxwidgets.org/wiki.pl?RTTI
//
#include "wx/html/forcelnk.h"
#ifdef __WXMSW__ // MSW has huge backends so we do it seperately
FORCE_LINK(wxmediabackend_am);
FORCE_LINK(wxmediabackend_wmp10);
#else
FORCE_LINK(basewxmediabackends);
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// End of compilation guard and of file // End of compilation guard and of file
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -12,29 +12,34 @@
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// There are several known bugs with CreateMovieControl // There are several known bugs with CreateMovieControl
// on systems > 10.2 - see main.c of QTCarbonShell sample for details // on systems > 10.2 - see main.c of QTCarbonShell sample for details
//
// Also, with either version it will overdraw anything below its TLW - so
// its relatively useless on a notebook page (this happens in Opera too).
//
// Even though though the CreateMovieControl version is the default
// for OSX, the MovieController version is heavily tested and works
// just as well...
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//===========================================================================
// DECLARATIONS
//===========================================================================
//---------------------------------------------------------------------------
// Pre-compiled header stuff
//---------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h". // For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h" #include "wx/wxprec.h"
#ifdef __BORLANDC__ //---------------------------------------------------------------------------
#pragma hdrstop // Includes
#endif //---------------------------------------------------------------------------
#include "wx/mediactrl.h" #include "wx/mediactrl.h"
// uma is for wxMacFSSpec //---------------------------------------------------------------------------
#include "wx/mac/uma.h" // Compilation guard
#include "wx/timer.h" //---------------------------------------------------------------------------
#ifndef __DARWIN__
#include <Movies.h>
#include <Gestalt.h>
#include <QuickTimeComponents.h> // standard QT stuff
#else
#include <QuickTime/QuickTimeComponents.h>
#endif
#if wxUSE_MEDIACTRL #if wxUSE_MEDIACTRL
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -61,9 +66,24 @@
//=========================================================================== //===========================================================================
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//
// wxQTMediaBackend // wxQTMediaBackend
//
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// QT Includes
//---------------------------------------------------------------------------
//uma is for wxMacFSSpec
#include "wx/mac/uma.h"
#include "wx/timer.h"
#ifndef __DARWIN__
#include <Movies.h>
#include <Gestalt.h>
#include <QuickTimeComponents.h> //Standard QT stuff
#else
#include <QuickTime/QuickTimeComponents.h>
#endif
class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
{ {
@@ -106,13 +126,22 @@ public:
virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags); virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
virtual wxLongLong GetDownloadProgress();
virtual wxLongLong GetDownloadTotal();
//
// ------ Implementation from now on -------- // ------ Implementation from now on --------
//
bool DoPause();
bool DoStop();
void DoLoadBestSize(); void DoLoadBestSize();
void DoSetControllerVisible(wxMediaCtrlPlayerControls flags); void DoSetControllerVisible(wxMediaCtrlPlayerControls flags);
wxLongLong GetDataSizeFromStart(TimeValue end);
//TODO: Last param actually long - does this work on 64bit machines? //TODO: Last param actually long - does this work on 64bit machines?
static Boolean MCFilterProc (MovieController theController, static pascal Boolean MCFilterProc (MovieController theController,
short action, void *params, long refCon); short action, void *params, long refCon);
#if wxUSE_CREATEMOVIECONTROL #if wxUSE_CREATEMOVIECONTROL
@@ -120,28 +149,28 @@ public:
#else #else
Boolean IsQuickTime4Installed(); Boolean IsQuickTime4Installed();
void DoNewMovieController(); void DoNewMovieController();
static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon); static pascal void PPRMProc (Movie theMovie,
OSErr theErr, void* theRefCon);
#endif #endif
wxSize m_bestSize; // Original movie size wxSize m_bestSize; // Original movie size
#ifdef __WXMAC_OSX__ #ifdef __WXMAC_OSX__
struct MovieType** m_movie; // QT Movie handle/instance struct MovieType** m_movie; // QT Movie handle/instance
#else #else
Movie m_movie; // Movie instance Movie m_movie; // Movie instance
#endif #endif
bool m_bPlaying; // Whether media is playing or not bool m_bPlaying; // Whether media is playing or not
class wxTimer* m_timer; // Timer for streaming the movie class wxTimer* m_timer; // Timer for streaming the movie
MovieController m_mc; // MovieController instance MovieController m_mc; // MovieController instance
wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
#if !wxUSE_CREATEMOVIECONTROL #if !wxUSE_CREATEMOVIECONTROL
EventHandlerRef m_pEventHandlerRef; // Event handler to cleanup EventHandlerRef m_pEventHandlerRef; // Event handler to cleanup
MoviePrePrerollCompleteUPP m_preprerollupp;
EventHandlerUPP m_eventupp;
MCActionFilterWithRefConUPP m_mcactionupp;
friend class wxQTMediaEvtHandler; friend class wxQTMediaEvtHandler;
#endif #endif
DECLARE_DYNAMIC_CLASS(wxQTMediaBackend) DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
}; };
@@ -154,8 +183,7 @@ public:
{ {
m_qtb = qtb; m_qtb = qtb;
qtb->m_ctrl->Connect( qtb->m_ctrl->Connect(qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground), wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
NULL, this); NULL, this);
} }
@@ -172,7 +200,6 @@ private:
static pascal OSStatus wxQTMediaWindowEventHandler( static pascal OSStatus wxQTMediaWindowEventHandler(
EventHandlerCallRef inHandlerCallRef, EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void *inUserData); EventRef inEvent, void *inUserData);
DEFINE_ONE_SHOT_HANDLER_GETTER( wxQTMediaWindowEventHandler );
#endif #endif
@@ -182,7 +209,9 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxQTMediaWindowEventHandler );
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxQTMediaBackend // wxQTMediaBackend
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend) IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)
@@ -213,9 +242,8 @@ public:
#if !wxUSE_CREATEMOVIECONTROL #if !wxUSE_CREATEMOVIECONTROL
::MCIdle(m_parent->m_mc); ::MCIdle(m_parent->m_mc);
#endif #endif
//kMovieLoadStatePlayable is not enough on MAC
// kMovieLoadStatePlayable is not enough on MAC: //- it plays, but IsMovieDone might return true (!)
// it plays, but IsMovieDone might return true (!)
//sure we need to wait until kMovieLoadStatePlaythroughOK //sure we need to wait until kMovieLoadStatePlaythroughOK
if(::GetMovieLoadState(m_movie) >= 20000) if(::GetMovieLoadState(m_movie) >= 20000)
{ {
@@ -262,8 +290,10 @@ public:
::MCIdle(m_parent->m_mc); ::MCIdle(m_parent->m_mc);
#endif #endif
//
// Handle the stop event - if the movie has reached // Handle the stop event - if the movie has reached
// the end, notify our handler // the end, notify our handler
//
if(::IsMovieDone(m_movie)) if(::IsMovieDone(m_movie))
{ {
if ( m_parent->SendStopEvent() ) if ( m_parent->SendStopEvent() )
@@ -290,6 +320,9 @@ protected:
wxQTMediaBackend::wxQTMediaBackend() wxQTMediaBackend::wxQTMediaBackend()
: m_movie(NULL), m_bPlaying(false), m_timer(NULL) : m_movie(NULL), m_bPlaying(false), m_timer(NULL)
, m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE) , m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
#if !wxUSE_CREATEMOVIECONTROL
, m_preprerollupp(NULL)
#endif
{ {
} }
@@ -314,7 +347,11 @@ wxQTMediaBackend::~wxQTMediaBackend()
// destroy wxQTMediaEvtHandler we pushed on it // destroy wxQTMediaEvtHandler we pushed on it
m_ctrl->PopEventHandler(true); m_ctrl->PopEventHandler(true);
RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef); RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
DisposeEventHandlerUPP(m_eventupp);
// Dispose of the movie controller
::DisposeMovieController(m_mc); ::DisposeMovieController(m_mc);
DisposeMCActionFilterWithRefConUPP(m_mcactionupp);
} }
#endif #endif
@@ -328,9 +365,7 @@ wxQTMediaBackend::~wxQTMediaBackend()
// 1) Intializes QuickTime // 1) Intializes QuickTime
// 2) Creates the control window // 2) Creates the control window
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool wxQTMediaBackend::CreateControl( bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
wxControl* ctrl,
wxWindow* parent,
wxWindowID id, wxWindowID id,
const wxPoint& pos, const wxPoint& pos,
const wxSize& size, const wxSize& size,
@@ -346,18 +381,19 @@ bool wxQTMediaBackend::CreateControl(
EnterMovies(); EnterMovies();
//
// Create window // Create window
// By default wxWindow(s) is created with a border - // By default wxWindow(s) is created with a border -
// so we need to get rid of those // so we need to get rid of those
// //
// Since we don't have a child window like most other // Since we don't have a child window like most other
// backends, we don't need wxCLIP_CHILDREN // backends, we don't need wxCLIP_CHILDREN
//
if ( !ctrl->wxControl::Create(parent, id, pos, size, if ( !ctrl->wxControl::Create(parent, id, pos, size,
wxWindow::MacRemoveBordersFromStyle(style), wxWindow::MacRemoveBordersFromStyle(style),
validator, name)) validator, name)
{ )
return false; return false;
}
#if wxUSE_VALIDATORS #if wxUSE_VALIDATORS
ctrl->SetValidator(validator); ctrl->SetValidator(validator);
@@ -376,7 +412,7 @@ bool wxQTMediaBackend::CreateControl(
#if !wxUSE_CREATEMOVIECONTROL #if !wxUSE_CREATEMOVIECONTROL
Boolean wxQTMediaBackend::IsQuickTime4Installed() Boolean wxQTMediaBackend::IsQuickTime4Installed()
{ {
OSErr error; short error;
long result; long result;
error = Gestalt (gestaltQuickTime, &result); error = Gestalt (gestaltQuickTime, &result);
@@ -415,7 +451,6 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
short movieResID = 0; short movieResID = 0;
Str255 movieName; Str255 movieName;
bool result;
err = NewMovieFromFile ( err = NewMovieFromFile (
&m_movie, &m_movie,
@@ -424,11 +459,10 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
movieName, movieName,
newMovieActive, newMovieActive,
NULL); //wasChanged NULL); //wasChanged
result = (err == noErr);
//No ::GetMoviesStickyError() here because it returns -2009 //No ::GetMoviesStickyError() here because it returns -2009
// a.k.a. invalid track on valid mpegs // a.k.a. invalid track on valid mpegs
if (result) if(err == noErr)
{ {
::CloseMovieFile (movieResFile); ::CloseMovieFile (movieResFile);
@@ -438,11 +472,13 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
#else #else
DoNewMovieController(); DoNewMovieController();
#endif #endif
FinishLoad(); FinishLoad();
return true;
}
else
{
return false;
} }
return result;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -453,7 +489,7 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
// Anyway we set up the loading timer here to tell us when the movie is done // Anyway we set up the loading timer here to tell us when the movie is done
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#if !wxUSE_CREATEMOVIECONTROL #if !wxUSE_CREATEMOVIECONTROL
void wxQTMediaBackend::PPRMProc (Movie theMovie, pascal void wxQTMediaBackend::PPRMProc (Movie theMovie,
OSErr WXUNUSED_UNLESS_DEBUG(theErr), OSErr WXUNUSED_UNLESS_DEBUG(theErr),
void* theRefCon) void* theRefCon)
{ {
@@ -490,13 +526,11 @@ bool wxQTMediaBackend::Load(const wxURI& location)
wxString theURI = location.BuildURI(); wxString theURI = location.BuildURI();
OSErr err = noErr; OSErr err = noErr;
bool result;
// FIXME: lurking Unicode problem here
Handle theHandle = ::NewHandleClear(theURI.length() + 1); Handle theHandle = ::NewHandleClear(theURI.length() + 1);
wxASSERT(theHandle); wxASSERT(theHandle);
::BlockMoveData(theURI.mb_str(), *theHandle, theURI.length() + 1); ::BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
//create the movie from the handle that refers to the URI //create the movie from the handle that refers to the URI
err = ::NewMovieFromDataRef(&m_movie, newMovieActive | err = ::NewMovieFromDataRef(&m_movie, newMovieActive |
@@ -507,11 +541,11 @@ bool wxQTMediaBackend::Load(const wxURI& location)
::DisposeHandle(theHandle); ::DisposeHandle(theHandle);
result = (err == noErr); if (err == noErr)
if (result)
{ {
#if wxUSE_CREATEMOVIECONTROL #if wxUSE_CREATEMOVIECONTROL
// Movie control resets prerolling, so we must create first // Movie control does its own "(pre)prerolling"
// but we still need to buffer the movie for the url
DoCreateMovieControl(); DoCreateMovieControl();
// Setup timer to catch load event // Setup timer to catch load event
@@ -530,6 +564,7 @@ bool wxQTMediaBackend::Load(const wxURI& location)
playRate = ::GetMoviePreferredRate(m_movie); playRate = ::GetMoviePreferredRate(m_movie);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
//
// Note that the callback here is optional, // Note that the callback here is optional,
// but without it PrePrerollMovie can be buggy // but without it PrePrerollMovie can be buggy
// (see Apple ml). Also, some may wonder // (see Apple ml). Also, some may wonder
@@ -538,14 +573,19 @@ bool wxQTMediaBackend::Load(const wxURI& location)
// require it if you don't use a Movie Controller, // require it if you don't use a Movie Controller,
// which we don't by default. // which we don't by default.
// //
::PrePrerollMovie( m_preprerollupp =
m_movie, timeNow, playRate, NewMoviePrePrerollCompleteUPP(
wxQTMediaBackend::PPRMProc, wxQTMediaBackend::PPRMProc
);
::PrePrerollMovie(m_movie, timeNow, playRate,
m_preprerollupp,
(void*)this); (void*)this);
#endif #endif
return true;
} }
else
return result; return false;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -562,10 +602,11 @@ bool wxQTMediaBackend::Load(const wxURI& location)
#if wxUSE_CREATEMOVIECONTROL #if wxUSE_CREATEMOVIECONTROL
void wxQTMediaBackend::DoCreateMovieControl() void wxQTMediaBackend::DoCreateMovieControl()
{ {
//
//Native CreateMovieControl QT control (Thanks to Kevin Olliver's //Native CreateMovieControl QT control (Thanks to Kevin Olliver's
// wxQTMovie for some of this). // wxQTMovie for how to do some of this).
Rect bounds = wxMacGetBoundsForControl( //
m_ctrl, Rect bounds = wxMacGetBoundsForControl(m_ctrl,
m_ctrl->GetPosition(), m_ctrl->GetPosition(),
m_ctrl->GetSize()); m_ctrl->GetSize());
@@ -573,7 +614,7 @@ void wxQTMediaBackend::DoCreateMovieControl()
if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() ) if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
m_ctrl->m_peer->Dispose(); m_ctrl->m_peer->Dispose();
// Options: //Options-
//kMovieControlOptionXXX //kMovieControlOptionXXX
//HideController - hide the movie controller //HideController - hide the movie controller
//LocateTopLeft - movie is pinned to top left rather than centered in the control //LocateTopLeft - movie is pinned to top left rather than centered in the control
@@ -593,23 +634,24 @@ void wxQTMediaBackend::DoCreateMovieControl()
, //flags , //flags
m_ctrl->m_peer->GetControlRefAddr() ); m_ctrl->m_peer->GetControlRefAddr() );
::EmbedControl( ::EmbedControl(m_ctrl->m_peer->GetControlRef(),
m_ctrl->m_peer->GetControlRef(),
(ControlRef)m_ctrl->GetParent()->GetHandle()); (ControlRef)m_ctrl->GetParent()->GetHandle());
// set up MovieController for the new movie //
// Setup MovieController for the new movie
//
long dataSize; long dataSize;
//Get movie controller from our control //Get movie controller from our control
::GetControlData( ::GetControlData( m_ctrl->m_peer->GetControlRef(), 0,
m_ctrl->m_peer->GetControlRef(), 0,
kMovieControlDataMovieController, kMovieControlDataMovieController,
sizeof(MovieController), (Ptr)&m_mc, &dataSize ); sizeof(MovieController), (Ptr)&m_mc, &dataSize );
// Setup a callback so we can tell when the user presses // Setup a callback so we can tell when the user presses
// play on the player controls // play on the player controls
::MCSetActionFilterWithRefCon(m_mc, ::MCSetActionFilterWithRefCon(m_mc,
wxQTMediaBackend::MCFilterProc, (long)this); (MCActionFilterWithRefConUPP)wxQTMediaBackend::MCFilterProc,
(long)this);
} }
#endif #endif
@@ -627,7 +669,7 @@ void wxQTMediaBackend::DoNewMovieController()
// Get top level window ref for some mac functions // Get top level window ref for some mac functions
WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef(); WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef();
// MovieController not setup yet: // MovieController not setup yet -
// so we need to create a new one. // so we need to create a new one.
// You have to pass a valid movie to // You have to pass a valid movie to
// NewMovieController, evidently // NewMovieController, evidently
@@ -636,23 +678,26 @@ void wxQTMediaBackend::DoNewMovieController()
NULL); NULL);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
Rect bounds = wxMacGetBoundsForControl( Rect bounds = wxMacGetBoundsForControl(m_ctrl,
m_ctrl,
m_ctrl->GetPosition(), m_ctrl->GetPosition(),
m_ctrl->GetSize()); m_ctrl->GetSize());
m_mc = ::NewMovieController( m_mc = ::NewMovieController(m_movie, &bounds, mcTopLeftMovie |
m_movie, &bounds, //mcWithFrame |
mcTopLeftMovie | mcNotVisible /* | mcWithFrame */ ); mcNotVisible);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
::MCDoAction(m_mc, 32, (void*)true); //mcActionSetKeysEnabled ::MCDoAction(m_mc, 32, (void*)true); //mcActionSetKeysEnabled
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
// Setup a callback so we can tell when the user presses // Setup a callback so we can tell when the user presses
// play on the player controls // play on the player controls
m_mcactionupp =
NewMCActionFilterWithRefConUPP(
wxQTMediaBackend::MCFilterProc
);
::MCSetActionFilterWithRefCon(m_mc, ::MCSetActionFilterWithRefCon(m_mc,
wxQTMediaBackend::MCFilterProc, (long)this); m_mcactionupp,
(long)this);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
//Part of a suggestion from Greg Hazel to repaint //Part of a suggestion from Greg Hazel to repaint
@@ -661,10 +706,10 @@ void wxQTMediaBackend::DoNewMovieController()
// Event types to catch from the TLW // Event types to catch from the TLW
// for the moviecontroller // for the moviecontroller
EventTypeSpec theEventTypes[] = EventTypeSpec theEventTypes[] = {
{
{ kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseUp },
{ kEventClassMouse, kEventMouseDragged },
{ kEventClassKeyboard, kEventRawKeyDown }, { kEventClassKeyboard, kEventRawKeyDown },
{ kEventClassKeyboard, kEventRawKeyRepeat }, { kEventClassKeyboard, kEventRawKeyRepeat },
{ kEventClassKeyboard, kEventRawKeyUp }, { kEventClassKeyboard, kEventRawKeyUp },
@@ -673,24 +718,26 @@ void wxQTMediaBackend::DoNewMovieController()
{ kEventClassWindow, kEventWindowDeactivated } { kEventClassWindow, kEventWindowDeactivated }
}; };
// Catch window messages: // Catch window messages -
// if we do not do this and if the user clicks the play // if we do not do this and if the user clicks the play
// button on the controller, for instance, nothing will happen... // button on the controller, for instance, nothing will happen...
m_eventupp = NewEventHandlerUPP(
wxQTMediaWindowEventHandler
);
InstallWindowEventHandler( wrTLW, InstallWindowEventHandler( wrTLW,
GetwxQTMediaWindowEventHandlerUPP(), m_eventupp,
GetEventTypeCount( theEventTypes ), theEventTypes, GetEventTypeCount( theEventTypes ), theEventTypes,
m_mc, (&(EventHandlerRef&)m_pEventHandlerRef) ); m_mc, (&(EventHandlerRef&)m_pEventHandlerRef) );
} }
else else
{ {
// MovieController already created: // MovieController already created -
// Just change the movie in it and we're good to go // Just change the movie in it and we're good to go
Point thePoint; Point thePoint;
thePoint.h = thePoint.v = 0; thePoint.h = thePoint.v = 0;
::MCSetMovie(m_mc, m_movie, ::MCSetMovie(m_mc, m_movie,
(WindowRef)m_ctrl->MacGetTopLevelWindowRef(), (WindowRef)m_ctrl->MacGetTopLevelWindowRef(),
thePoint); thePoint);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
} }
} }
@@ -703,10 +750,14 @@ void wxQTMediaBackend::DoNewMovieController()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void wxQTMediaBackend::FinishLoad() void wxQTMediaBackend::FinishLoad()
{ {
// Dispose of the Preprerollmovieupp if we used it
#if !wxUSE_CREATEMOVIECONTROL
DisposeMoviePrePrerollCompleteUPP(m_preprerollupp);
#endif
// get the real size of the movie // get the real size of the movie
DoLoadBestSize(); DoLoadBestSize();
// show the player controls if the user wants to // Show the player controls if the user wants to
if(m_interfaceflags) if(m_interfaceflags)
DoSetControllerVisible(m_interfaceflags); DoSetControllerVisible(m_interfaceflags);
@@ -714,7 +765,7 @@ void wxQTMediaBackend::FinishLoad()
::SetMovieTimeScale(m_movie, 1000); ::SetMovieTimeScale(m_movie, 1000);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
// start movie progress timer // Start movie progress timer
m_timer = new wxQTMediaPlayTimer(m_movie, (wxQTMediaBackend*) this); m_timer = new wxQTMediaPlayTimer(m_movie, (wxQTMediaBackend*) this);
wxASSERT(m_timer); wxASSERT(m_timer);
m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
@@ -744,6 +795,7 @@ void wxQTMediaBackend::DoLoadBestSize()
// wxQTMediaBackend::Play // wxQTMediaBackend::Play
// //
// Start the QT movie // Start the QT movie
// (Apple recommends mcActionPrerollAndPlay but that's QT 4.1+)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool wxQTMediaBackend::Play() bool wxQTMediaBackend::Play()
{ {
@@ -754,10 +806,18 @@ bool wxQTMediaBackend::Play()
wxASSERT(fixRate != 0); wxASSERT(fixRate != 0);
if(!m_bPlaying) if(!m_bPlaying)
::MCDoAction( m_mc, 8 /* mcActionPlay */, (void*) fixRate); ::MCDoAction( m_mc, 8, // mcActionPlay
(void *) fixRate);
if(::GetMoviesError() == noErr)
{
m_bPlaying = true; m_bPlaying = true;
return ::GetMoviesError() == noErr; QueuePlayEvent();
return true;
}
else
return false;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -765,19 +825,30 @@ bool wxQTMediaBackend::Play()
// //
// Stop the movie // Stop the movie
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool wxQTMediaBackend::Pause() bool wxQTMediaBackend::DoPause()
{ {
//Stop the movie A.K.A. ::StopMovie(m_movie); //Stop the movie A.K.A. ::StopMovie(m_movie);
if(m_bPlaying) if(m_bPlaying)
{ {
::MCDoAction( m_mc, 8 /*mcActionPlay*/, (void*) 0); ::MCDoAction( m_mc, 8 /*mcActionPlay*/,
(void *) 0);
m_bPlaying = false; m_bPlaying = false;
return ::GetMoviesError() == noErr; return ::GetMoviesError() == noErr;
} }
return true; //already paused
}
// already paused bool wxQTMediaBackend::Pause()
{
bool bSuccess = DoPause();
if(bSuccess)
{
this->QueuePauseEvent();
return true; return true;
} }
else
return false;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxQTMediaBackend::Stop // wxQTMediaBackend::Stop
@@ -785,15 +856,27 @@ bool wxQTMediaBackend::Pause()
// 1) Stop the movie // 1) Stop the movie
// 2) Seek to the beginning of the movie // 2) Seek to the beginning of the movie
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool wxQTMediaBackend::Stop() bool wxQTMediaBackend::DoStop()
{ {
if (!wxQTMediaBackend::Pause()) if(!wxQTMediaBackend::DoPause())
return false; return false;
::GoToBeginningOfMovie(m_movie); ::GoToBeginningOfMovie(m_movie);
return ::GetMoviesError() == noErr; return ::GetMoviesError() == noErr;
} }
bool wxQTMediaBackend::Stop()
{
bool bSuccess = DoStop();
if(bSuccess)
{
QueueStopEvent();
return true;
}
else
return false;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxQTMediaBackend::GetPlaybackRate // wxQTMediaBackend::GetPlaybackRate
// //
@@ -913,7 +996,7 @@ wxMediaState wxQTMediaBackend::GetState()
// Could use // Could use
// GetMovieActive/IsMovieDone/SetMovieActive // GetMovieActive/IsMovieDone/SetMovieActive
// combo if implemented that way // combo if implemented that way
if (m_bPlaying) if (m_bPlaying == true)
return wxMEDIASTATE_PLAYING; return wxMEDIASTATE_PLAYING;
else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0) else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
return wxMEDIASTATE_STOPPED; return wxMEDIASTATE_STOPPED;
@@ -936,7 +1019,7 @@ void wxQTMediaBackend::Cleanup()
m_timer = NULL; m_timer = NULL;
} }
// Stop the movie: // Stop the movie
// Apple samples with CreateMovieControl typically // Apple samples with CreateMovieControl typically
// install a event handler and do this on the dispose // install a event handler and do this on the dispose
// event, but we do it here for simplicity // event, but we do it here for simplicity
@@ -944,7 +1027,9 @@ void wxQTMediaBackend::Cleanup()
// control destruction if not) // control destruction if not)
wxQTMediaBackend::Pause(); wxQTMediaBackend::Pause();
//
// Dispose of control or remove movie from MovieController // Dispose of control or remove movie from MovieController
//
#if wxUSE_CREATEMOVIECONTROL #if wxUSE_CREATEMOVIECONTROL
if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() ) if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
m_ctrl->m_peer->Dispose(); m_ctrl->m_peer->Dispose();
@@ -956,7 +1041,6 @@ void wxQTMediaBackend::Cleanup()
#endif #endif
::DisposeMovie(m_movie); ::DisposeMovie(m_movie);
m_movie = NULL;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -964,30 +1048,26 @@ void wxQTMediaBackend::Cleanup()
// //
// Callback for when the movie controller recieves a message // Callback for when the movie controller recieves a message
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
Boolean wxQTMediaBackend::MCFilterProc( pascal Boolean wxQTMediaBackend::MCFilterProc(
MovieController WXUNUSED(theController), MovieController WXUNUSED(theController),
short action, short action,
void * WXUNUSED(params), void * WXUNUSED(params),
long refCon) long refCon)
{
if(action != 1) //don't process idle events
{ {
wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon; wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
switch(action) switch(action)
{ {
case 1: case 8: //play button triggered - MC will set movie to opposite state
// don't process idle events
break;
case 8:
// play button triggered - MC will set movie to opposite state
//of current - playing ? paused : playing //of current - playing ? paused : playing
pThis->m_bPlaying = !(pThis->m_bPlaying); pThis->m_bPlaying = !(pThis->m_bPlaying);
break; break;
default: default:
break; break;
} }
}
return 0; return 0;
} }
@@ -1004,8 +1084,15 @@ wxSize wxQTMediaBackend::GetVideoSize() const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxQTMediaBackend::Move // wxQTMediaBackend::Move
// //
// We need to do this even when using native qt control because // Move the movie controller or movie control
// CreateMovieControl is broken in this regard... // (we need to actually move the movie control manually...)
// Top 10 things to do with quicktime in March 93's issue
// of DEVELOP - very useful
// http:// www.mactech.com/articles/develop/issue_13/031-033_QuickTime_column.html
// OLD NOTE: Calling MCSetControllerBoundsRect without detaching
// supposively resulted in a crash back then. Current code even
// with CFM classic runs fine. If there is ever a problem,
// take out the if 0 lines below
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void wxQTMediaBackend::Move(int x, int y, int w, int h) void wxQTMediaBackend::Move(int x, int y, int w, int h)
{ {
@@ -1014,9 +1101,20 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h)
{ {
m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y);
Rect theRect = {y, x, y+h, x+w}; Rect theRect = {y, x, y+h, x+w};
#if 0 // see note above
::MCSetControllerAttached(m_mc, FALSE);
wxASSERT(::GetMoviesError() == noErr);
#endif
::MCSetControllerBoundsRect(m_mc, &theRect); ::MCSetControllerBoundsRect(m_mc, &theRect);
wxASSERT(::GetMoviesError() == noErr); wxASSERT(::GetMoviesError() == noErr);
#if 0 // see note above
if(m_interfaceflags)
{
::MCSetVisible(m_mc, TRUE);
wxASSERT(::GetMoviesError() == noErr);
}
#endif
} }
#else #else
if(m_timer && m_ctrl) if(m_timer && m_ctrl)
@@ -1038,9 +1136,11 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags) void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags)
{ {
::MCSetVisible(m_mc, true); ::MCSetVisible(m_mc, TRUE);
//
// Take care of subcontrols // Take care of subcontrols
//
if(::GetMoviesError() == noErr) if(::GetMoviesError() == noErr)
{ {
long mcFlags = 0; long mcFlags = 0;
@@ -1056,13 +1156,14 @@ void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags)
? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/) ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
// | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves // | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
); );
::MCDoAction(m_mc, 38/*mcActionSetFlags*/, (void*)mcFlags); ::MCDoAction(m_mc, 38/*mcActionSetFlags*/, (void*)mcFlags);
} }
} }
//
//Adjust height and width of best size for movie controller //Adjust height and width of best size for movie controller
//if the user wants it shown //if the user wants it shown
//
m_bestSize.x = m_bestSize.x > wxMCWIDTH ? m_bestSize.x : wxMCWIDTH; m_bestSize.x = m_bestSize.x > wxMCWIDTH ? m_bestSize.x : wxMCWIDTH;
m_bestSize.y += wxMCHEIGHT; m_bestSize.y += wxMCHEIGHT;
} }
@@ -1084,7 +1185,7 @@ bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
{ {
bSizeChanged = true; bSizeChanged = true;
DoLoadBestSize(); DoLoadBestSize();
::MCSetVisible(m_mc, false); ::MCSetVisible(m_mc, FALSE);
} }
else if(!m_interfaceflags && flags) //show controller if hidden else if(!m_interfaceflags && flags) //show controller if hidden
{ {
@@ -1100,10 +1201,59 @@ bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
//remember state in case of loading new media //remember state in case of loading new media
m_interfaceflags = flags; m_interfaceflags = flags;
} }
return ::GetMoviesError() == noErr; return ::GetMoviesError() == noErr;
} }
//---------------------------------------------------------------------------
// wxQTMediaBackend::GetDataSizeFromStart
//
// Calls either GetMovieDataSize or GetMovieDataSize64 with a value
// of 0 for the starting value
//---------------------------------------------------------------------------
wxLongLong wxQTMediaBackend::GetDataSizeFromStart(TimeValue end)
{
#if 0 // old pre-qt4 way
return ::GetMovieDataSize(m_movie, 0, end)
#else // qt4 way
wide llDataSize;
::GetMovieDataSize64(m_movie, 0, end, &llDataSize);
return wxLongLong(llDataSize.hi, llDataSize.lo);
#endif
}
//---------------------------------------------------------------------------
// wxQTMediaBackend::GetDownloadProgress
//---------------------------------------------------------------------------
wxLongLong wxQTMediaBackend::GetDownloadProgress()
{
#if 0 // hackish and slow
Handle hMovie = NewHandle(0);
PutMovieIntoHandle(m_movie, hMovie);
long lSize = GetHandleSize(hMovie);
DisposeHandle(hMovie);
return lSize;
#else
TimeValue tv;
if(::GetMaxLoadedTimeInMovie(m_movie, &tv) != noErr)
{
wxLogDebug(wxT("GetMaxLoadedTimeInMovie failed"));
return 0;
}
return wxQTMediaBackend::GetDataSizeFromStart(tv);
#endif
}
//---------------------------------------------------------------------------
// wxQTMediaBackend::GetDownloadTotal
//---------------------------------------------------------------------------
wxLongLong wxQTMediaBackend::GetDownloadTotal()
{
return wxQTMediaBackend::GetDataSizeFromStart(
::GetMovieDuration(m_movie)
);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// wxQTMediaBackend::OnEraseBackground // wxQTMediaBackend::OnEraseBackground
// //
@@ -1118,9 +1268,9 @@ void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
WindowRef wrTLW = WindowRef wrTLW =
(WindowRef) m_qtb->m_ctrl->MacGetTopLevelWindowRef(); (WindowRef) m_qtb->m_ctrl->MacGetTopLevelWindowRef();
RgnHandle region = MCGetControllerBoundsRgn(m_qtb->m_mc); RgnHandle region = ::MCGetControllerBoundsRgn(m_qtb->m_mc);
MCInvalidate(m_qtb->m_mc, wrTLW, region); ::MCInvalidate(m_qtb->m_mc, wrTLW, region);
MCIdle(m_qtb->m_mc); ::MCIdle(m_qtb->m_mc);
} }
#endif #endif
@@ -1131,17 +1281,34 @@ void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
// messages to our moviecontroller so it can recieve mouse clicks etc. // messages to our moviecontroller so it can recieve mouse clicks etc.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#if !wxUSE_CREATEMOVIECONTROL #if !wxUSE_CREATEMOVIECONTROL
OSStatus wxQTMediaWindowEventHandler( static pascal OSStatus wxQTMediaWindowEventHandler(
EventHandlerCallRef inHandlerCallRef, EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void *inUserData) EventRef inEvent, void *inUserData)
{ {
// for the overly paranoid....
#if 0
UInt32 eventClass = GetEventClass( eventRef );
UInt32 eventKind = GetEventKind( inEvent );
if(eventKind != kEventMouseDown &&
eventKind != kEventMouseUp &&
eventKind != kEventMouseDragged &&
eventKind != kEventRawKeyDown &&
eventKind != kEventRawKeyRepeat &&
eventKind != kEventRawKeyUp &&
eventKind != kEventWindowUpdate &&
eventKind != kEventWindowActivated &&
eventKind != kEventWindowDeactivated )
return eventNotHandledErr;
#endif
EventRecord theEvent; EventRecord theEvent;
ConvertEventRefToEventRecord( inEvent, &theEvent ); ConvertEventRefToEventRecord( inEvent, &theEvent );
OSStatus err; OSStatus err;
err = ::MCIsPlayerEvent( (MovieController) inUserData, &theEvent ); err = ::MCIsPlayerEvent( (MovieController) inUserData, &theEvent );
// pass on to other event handlers if not handled- i.e. wx // pass on to other event handlers if not handled- i.e. wx
if (err != noErr) if(err)
return noErr; return noErr;
else else
return eventNotHandledErr; return eventNotHandledErr;

2269
src/msw/mediactrl_am.cpp Normal file

File diff suppressed because it is too large Load Diff

1521
src/msw/mediactrl_wmp10.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: src/msw/ole/activex.cpp // Name: msw/ole/activex.cpp
// Purpose: wxActiveXContainer implementation // Purpose: wxActiveXContainer implementation
// Author: Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???> // Author: Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
// Modified by: // Modified by:
@@ -25,15 +25,25 @@
#include "wx/dcclient.h" #include "wx/dcclient.h"
#include "wx/math.h" #include "wx/math.h"
// I don't know why members of tagVARIANT aren't found when compiling
// with Wine
#ifndef __WINE__
#include "wx/msw/ole/activex.h" #include "wx/msw/ole/activex.h"
// autointerfaces that we only use here
WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
WX_DECLARE_AUTOOLE(wxAutoIProvideClassInfo, IProvideClassInfo)
WX_DECLARE_AUTOOLE(wxAutoITypeInfo, ITypeInfo)
WX_DECLARE_AUTOOLE(wxAutoIConnectionPoint, IConnectionPoint)
WX_DECLARE_AUTOOLE(wxAutoIConnectionPointContainer, IConnectionPointContainer)
DEFINE_EVENT_TYPE(wxEVT_ACTIVEX);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Ole class helpers (sort of MFC-like) from wxActiveX
//
// wxActiveXContainer
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define DECLARE_OLE_UNKNOWN(cls)\ #define DECLARE_OLE_UNKNOWN(cls)\
private:\ private:\
class TAutoInitInt\ class TAutoInitInt\
@@ -59,21 +69,21 @@
if (! ppvObject)\ if (! ppvObject)\
{\ {\
return E_FAIL;\ return E_FAIL;\
}\ };\
const char *desc = NULL;\ const char *desc = NULL;\
cls::_GetInterface(this, iid, ppvObject, desc);\ cls::_GetInterface(this, iid, ppvObject, desc);\
if (! *ppvObject)\ if (! *ppvObject)\
{\ {\
return E_NOINTERFACE;\ return E_NOINTERFACE;\
}\ };\
((IUnknown * )(*ppvObject))->AddRef();\ ((IUnknown * )(*ppvObject))->AddRef();\
return S_OK;\ return S_OK;\
}\ };\
ULONG STDMETHODCALLTYPE cls::AddRef()\ ULONG STDMETHODCALLTYPE cls::AddRef()\
{\ {\
InterlockedIncrement(&refCount.l);\ InterlockedIncrement(&refCount.l);\
return refCount.l;\ return refCount.l;\
}\ };\
ULONG STDMETHODCALLTYPE cls::Release()\ ULONG STDMETHODCALLTYPE cls::Release()\
{\ {\
if (refCount.l > 0)\ if (refCount.l > 0)\
@@ -83,7 +93,7 @@
{\ {\
delete this;\ delete this;\
return 0;\ return 0;\
}\ };\
return refCount.l;\ return refCount.l;\
}\ }\
else\ else\
@@ -93,7 +103,7 @@
{\ {\
InterlockedIncrement(&lockCount.l);\ InterlockedIncrement(&lockCount.l);\
return lockCount.l;\ return lockCount.l;\
}\ };\
ULONG STDMETHODCALLTYPE cls::ReleaseLock()\ ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
{\ {\
if (lockCount.l > 0)\ if (lockCount.l > 0)\
@@ -131,7 +141,52 @@
#define END_OLE_TABLE\ #define END_OLE_TABLE\
} }
// ============================================================================
// implementation
// ============================================================================
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PixelsToHimetric
//
// Utility to convert from pixels to the himetric values in some COM methods
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define HIMETRIC_PER_INCH 2540
#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
static void PixelsToHimetric(SIZEL &sz)
{
static int logX = 0;
static int logY = 0;
if (logY == 0)
{
// initaliase
HDC dc = GetDC(NULL);
logX = GetDeviceCaps(dc, LOGPIXELSX);
logY = GetDeviceCaps(dc, LOGPIXELSY);
ReleaseDC(NULL, dc);
};
#define HIMETRIC_INCH 2540
#define CONVERT(x, logpixels) wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
sz.cx = CONVERT(sz.cx, logX);
sz.cy = CONVERT(sz.cy, logY);
#undef CONVERT
#undef HIMETRIC_INCH
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// FrameSite
//
// Handles the actual wxActiveX container implementation
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class FrameSite : class FrameSite :
public IOleClientSite, public IOleClientSite,
public IOleInPlaceSiteEx, public IOleInPlaceSiteEx,
@@ -207,7 +262,7 @@ public:
case DISPID_AMBIENT_SILENT: case DISPID_AMBIENT_SILENT:
V_BOOL(pVarResult)= TRUE; V_BOOL(pVarResult)= TRUE;
return S_OK; return S_OK;
#ifndef __WINE__
case DISPID_AMBIENT_APPEARANCE: case DISPID_AMBIENT_APPEARANCE:
pVarResult->vt = VT_BOOL; pVarResult->vt = VT_BOOL;
pVarResult->boolVal = m_bAmbientAppearance; pVarResult->boolVal = m_bAmbientAppearance;
@@ -242,7 +297,7 @@ public:
pVarResult->vt = VT_BOOL; pVarResult->vt = VT_BOOL;
pVarResult->boolVal = m_bAmbientShowHatching; pVarResult->boolVal = m_bAmbientShowHatching;
break; break;
#endif
default: default:
return DISP_E_MEMBERNOTFOUND; return DISP_E_MEMBERNOTFOUND;
} }
@@ -326,7 +381,7 @@ public:
if (! SUCCEEDED(hr)) if (! SUCCEEDED(hr))
{ {
return E_UNEXPECTED; return E_UNEXPECTED;
} };
hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc); hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
if (! SUCCEEDED(hr)) if (! SUCCEEDED(hr))
@@ -334,7 +389,7 @@ public:
(*ppFrame)->Release(); (*ppFrame)->Release();
*ppFrame = NULL; *ppFrame = NULL;
return E_UNEXPECTED; return E_UNEXPECTED;
} };
RECT rect; RECT rect;
::GetClientRect(m_hWndParent, &rect); ::GetClientRect(m_hWndParent, &rect);
@@ -343,13 +398,13 @@ public:
lprcPosRect->left = lprcPosRect->top = 0; lprcPosRect->left = lprcPosRect->top = 0;
lprcPosRect->right = rect.right; lprcPosRect->right = rect.right;
lprcPosRect->bottom = rect.bottom; lprcPosRect->bottom = rect.bottom;
} };
if (lprcClipRect) if (lprcClipRect)
{ {
lprcClipRect->left = lprcClipRect->top = 0; lprcClipRect->left = lprcClipRect->top = 0;
lprcClipRect->right = rect.right; lprcClipRect->right = rect.right;
lprcClipRect->bottom = rect.bottom; lprcClipRect->bottom = rect.bottom;
} };
memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO)); memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
@@ -368,8 +423,18 @@ public:
{ {
if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect) if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
{ {
//
// Result of several hours and days of bug hunting -
// this is called by an object when it wants to resize
// itself to something different then our parent window -
// don't let it :)
//
// m_window->m_oleInPlaceObject->SetObjectRects(
// lprcPosRect, lprcPosRect);
RECT rcClient;
::GetClientRect(m_hWndParent, &rcClient);
m_window->m_oleInPlaceObject->SetObjectRects( m_window->m_oleInPlaceObject->SetObjectRects(
lprcPosRect, lprcPosRect); &rcClient, &rcClient);
} }
return S_OK; return S_OK;
} }
@@ -419,8 +484,8 @@ public:
case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN"; case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN";
case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER"; case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER";
default : return "Bad Enum"; default : return "Bad Enum";
} };
} };
const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker) const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
{ {
@@ -430,8 +495,8 @@ public:
case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL"; case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL";
case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL"; case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL";
default : return "Bad Enum"; default : return "Bad Enum";
} };
} };
STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;} STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer) HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
{ {
@@ -458,7 +523,7 @@ public:
HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;} HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
//********************IOleItemContainer*************************** //********************IOleItemContainer***************************
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
#if defined(__WXWINCE__) #ifdef __WXWINCE__
GetObject GetObject
#elif defined(_UNICODE) #elif defined(_UNICODE)
GetObjectW GetObjectW
@@ -558,11 +623,11 @@ public:
return E_FAIL; return E_FAIL;
m_window->m_docView->SetInPlaceSite(inPlaceSite); m_window->m_docView->SetInPlaceSite(inPlaceSite);
} };
m_window->m_docView->UIActivate(TRUE); m_window->m_docView->UIActivate(TRUE);
return S_OK; return S_OK;
} };
protected: protected:
@@ -601,10 +666,135 @@ DEFINE_OLE_TABLE(FrameSite)
OLE_IINTERFACE(IOleDocumentSite) OLE_IINTERFACE(IOleDocumentSite)
OLE_IINTERFACE(IAdviseSink) OLE_IINTERFACE(IAdviseSink)
OLE_IINTERFACE(IOleControlSite) OLE_IINTERFACE(IOleControlSite)
END_OLE_TABLE END_OLE_TABLE;
wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown* pUnk) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxActiveXEvents
//
// Handles and sends activex events received from the ActiveX control
// to the appropriate wxEvtHandler
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class wxActiveXEvents : public IDispatch
{
private:
DECLARE_OLE_UNKNOWN(wxActiveXEvents);
wxActiveXContainer *m_activeX;
IID m_customId;
bool m_haveCustomId;
friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
public:
wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_haveCustomId(true), m_customId(iid) {}
virtual ~wxActiveXEvents()
{
}
// IDispatch
STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfoCount(unsigned int*)
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID WXUNUSED(riid),
LCID WXUNUSED(lcid),
WORD wFlags, DISPPARAMS * pDispParams,
VARIANT * WXUNUSED(pVarResult), EXCEPINFO * WXUNUSED(pExcepInfo),
unsigned int * WXUNUSED(puArgErr))
{
if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
return E_NOTIMPL;
wxASSERT(m_activeX);
// ActiveX Event
// Dispatch Event
wxActiveXEvent event;
event.SetEventType(wxEVT_ACTIVEX);
event.m_params.NullList();
event.m_dispid = dispIdMember;
// arguments
if (pDispParams)
{
for (DWORD i = pDispParams->cArgs; i > 0; i--)
{
VARIANTARG& va = pDispParams->rgvarg[i-1];
wxVariant vx;
// vx.SetName(px.name);
wxConvertOleToVariant(va, vx);
event.m_params.Append(vx);
}
}
// process the events from the activex method
m_activeX->ProcessEvent(event);
for (DWORD i = 0; i < pDispParams->cArgs; i++)
{
VARIANTARG& va = pDispParams->rgvarg[i];
wxVariant& vx =
event.m_params[pDispParams->cArgs - i - 1];
wxConvertVariantToOle(vx, va);
}
if(event.GetSkipped())
return DISP_E_MEMBERNOTFOUND;
return S_OK;
}
};
bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
{
if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
{
// WXOLE_TRACE("Found Custom Dispatch Interface");
*_interface = (IUnknown *) (IDispatch *) self;
desc = "Custom Dispatch Interface";
return true;
};
return false;
}
DEFINE_OLE_TABLE(wxActiveXEvents)
OLE_IINTERFACE(IUnknown)
OLE_INTERFACE(IID_IDispatch, IDispatch)
OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
END_OLE_TABLE;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxActiveXContainer
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//---------------------------------------------------------------------------
// wxActiveXContainer Constructor
//
// Initializes members and creates the native ActiveX container
//---------------------------------------------------------------------------
wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
REFIID iid, IUnknown* pUnk)
: m_realparent(parent) : m_realparent(parent)
{ {
m_bAmbientUserMode = true; m_bAmbientUserMode = true;
@@ -612,6 +802,12 @@ wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown*
CreateActiveX(iid, pUnk); CreateActiveX(iid, pUnk);
} }
//---------------------------------------------------------------------------
// wxActiveXContainer Destructor
//
// Destroys members (the FrameSite et al. are destroyed implicitly
// through COM ref counting)
//---------------------------------------------------------------------------
wxActiveXContainer::~wxActiveXContainer() wxActiveXContainer::~wxActiveXContainer()
{ {
// disconnect connection points // disconnect connection points
@@ -633,6 +829,14 @@ wxActiveXContainer::~wxActiveXContainer()
} }
} }
//---------------------------------------------------------------------------
// wxActiveXContainer::CreateActiveX
//
// Actually creates the ActiveX container through the FrameSite
// and sets up ActiveX events
//
// TODO: Document this more
//---------------------------------------------------------------------------
void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
{ {
HRESULT hret; HRESULT hret;
@@ -652,6 +856,111 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
// Get Dispatch interface // Get Dispatch interface
hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX); hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
//
// SETUP TYPEINFO AND ACTIVEX EVENTS
//
// get type info via class info
wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
wxASSERT(classInfo.Ok());
// type info
wxAutoITypeInfo typeInfo;
hret = classInfo->GetClassInfo(typeInfo.GetRef());
wxASSERT(typeInfo.Ok());
// TYPEATTR
TYPEATTR *ta = NULL;
hret = typeInfo->GetTypeAttr(&ta);
wxASSERT(ta);
// this should be a TKIND_COCLASS
wxASSERT(ta->typekind == TKIND_COCLASS);
// iterate contained interfaces
for (int i = 0; i < ta->cImplTypes; i++)
{
HREFTYPE rt = 0;
// get dispatch type info handle
hret = typeInfo->GetRefTypeOfImplType(i, &rt);
if (! SUCCEEDED(hret))
continue;
// get dispatch type info interface
wxAutoITypeInfo ti;
hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
if (! ti.Ok())
continue;
// check if default event sink
bool defInterface = false;
bool defEventSink = false;
int impTypeFlags = 0;
typeInfo->GetImplTypeFlags(i, &impTypeFlags);
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
{
if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
{
// WXOLE_TRACEOUT("Default Event Sink");
defEventSink = true;
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
{
// WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
defEventSink = false;
wxFAIL_MSG(wxT("Default event sink is in vtable!"));
}
}
else
{
// WXOLE_TRACEOUT("Default Interface");
defInterface = true;
}
}
// wxAutoOleInterface<> assumes a ref has already been added
// TYPEATTR
TYPEATTR *ta = NULL;
hret = ti->GetTypeAttr(&ta);
wxASSERT(ta);
if (ta->typekind == TKIND_DISPATCH)
{
// WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
if (defEventSink)
{
wxAutoIConnectionPoint cp;
DWORD adviseCookie = 0;
wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
wxASSERT( cpContainer.Ok());
HRESULT hret =
cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
wxASSERT ( SUCCEEDED(hret));
IDispatch* disp;
frame->QueryInterface(IID_IDispatch, (void**)&disp);
hret = cp->Advise(new wxActiveXEvents(this, ta->guid),
&adviseCookie);
wxASSERT_MSG( SUCCEEDED(hret),
wxString::Format(wxT("Cannot connect!\nHRESULT:%X"), hret)
);
}
}
ti->ReleaseTypeAttr(ta);
}
// free
typeInfo->ReleaseTypeAttr(ta);
//
// END
//
// Get IOleObject interface // Get IOleObject interface
hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX); hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
wxASSERT(SUCCEEDED(hret)); wxASSERT(SUCCEEDED(hret));
@@ -663,6 +972,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
// document advise // document advise
m_docAdviseCookie = 0; m_docAdviseCookie = 0;
hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie); hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
// TODO:Needed?
// hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
m_oleObject->SetHostNames(L"wxActiveXContainer", NULL); m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
OleSetContainedObject(m_oleObject, TRUE); OleSetContainedObject(m_oleObject, TRUE);
OleRun(m_oleObject); OleRun(m_oleObject);
@@ -739,6 +1050,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
pWnd->Connect(id, wxEVT_SIZE, pWnd->Connect(id, wxEVT_SIZE,
wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this); wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
// this->Connect(GetId(), wxEVT_PAINT,
// wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
pWnd->Connect(id, wxEVT_SET_FOCUS, pWnd->Connect(id, wxEVT_SET_FOCUS,
wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this); wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
pWnd->Connect(id, wxEVT_KILL_FOCUS, pWnd->Connect(id, wxEVT_KILL_FOCUS,
@@ -746,34 +1059,12 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
} }
} }
#define HIMETRIC_PER_INCH 2540 //---------------------------------------------------------------------------
#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) // wxActiveXContainer::OnSize
//
static void PixelsToHimetric(SIZEL &sz) // Called when the parent is resized - we need to do this to actually
{ // move the ActiveX control to where the parent is
static int logX = 0; //---------------------------------------------------------------------------
static int logY = 0;
if (logY == 0)
{
// initaliase
HDC dc = GetDC(NULL);
logX = GetDeviceCaps(dc, LOGPIXELSX);
logY = GetDeviceCaps(dc, LOGPIXELSY);
ReleaseDC(NULL, dc);
};
#define HIMETRIC_INCH 2540
#define CONVERT(x, logpixels) wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
sz.cx = CONVERT(sz.cx, logX);
sz.cy = CONVERT(sz.cy, logY);
#undef CONVERT
#undef HIMETRIC_INCH
}
void wxActiveXContainer::OnSize(wxSizeEvent& event) void wxActiveXContainer::OnSize(wxSizeEvent& event)
{ {
int w, h; int w, h;
@@ -791,6 +1082,9 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
// extents are in HIMETRIC units // extents are in HIMETRIC units
if (m_oleObject.Ok()) if (m_oleObject.Ok())
{ {
m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0,
(HWND)m_realparent->GetHWND(), &posRect);
SIZEL sz = {w, h}; SIZEL sz = {w, h};
PixelsToHimetric(sz); PixelsToHimetric(sz);
@@ -799,7 +1093,10 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2); m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
if (sz2.cx != sz.cx || sz.cy != sz2.cy) if (sz2.cx != sz.cx || sz.cy != sz2.cy)
m_oleObject->SetExtent(DVASPECT_CONTENT, &sz); m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
};
m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
(HWND)m_realparent->GetHWND(), &posRect);
}
if (m_oleInPlaceObject.Ok()) if (m_oleInPlaceObject.Ok())
m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
@@ -807,12 +1104,39 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
event.Skip(); event.Skip();
} }
//---------------------------------------------------------------------------
// wxActiveXContainer::OnPaint
//
// Called when the parent is resized - repaints the ActiveX control
//---------------------------------------------------------------------------
void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event)) void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
{ {
wxPaintDC dc(this); wxPaintDC dc(this);
// Draw only when control is windowless or deactivated // Draw only when control is windowless or deactivated
if (m_viewObject) if (m_viewObject)
{ {
#if 0
dc.BeginDrawing();
RECT rcClient;
::GetClientRect((HWND)GetHandle(), &rcClient);
HBITMAP hBitmap = CreateCompatibleBitmap((HDC)dc.GetHDC(),
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top);
HDC hdcCompatible = ::CreateCompatibleDC((HDC)dc.GetHDC());
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcCompatible, hBitmap);
m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
hdcCompatible, (RECTL *) &rcClient, (RECTL *) &rcClient, NULL, 0);
::BitBlt((HDC)dc.GetHDC(), 0, 0, rcClient.right, rcClient.bottom, hdcCompatible, 0, 0, SRCCOPY);
::SelectObject(hdcCompatible, hBitmapOld);
::DeleteObject(hBitmap);
::DeleteDC(hdcCompatible);
dc.EndDrawing();
#else
dc.BeginDrawing();
int w, h; int w, h;
GetParent()->GetSize(&w, &h); GetParent()->GetSize(&w, &h);
RECT posRect; RECT posRect;
@@ -821,20 +1145,21 @@ void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
posRect.right = w; posRect.right = w;
posRect.bottom = h; posRect.bottom = h;
#if defined(_WIN32_WCE) && _WIN32_WCE < 400
::InvalidateRect(m_oleObjectHWND, NULL, false);
#else
::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT); ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
#endif
RECTL *prcBounds = (RECTL *) &posRect; RECTL *prcBounds = (RECTL *) &posRect;
m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
(HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0); (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
dc.EndDrawing();
#endif
}
} }
// We've got this one I think //---------------------------------------------------------------------------
// event.Skip(); // wxActiveXContainer::OnSetFocus
} //
// Called when the focus is set on the parent - activates the activex control
//---------------------------------------------------------------------------
void wxActiveXContainer::OnSetFocus(wxFocusEvent& event) void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
{ {
if (m_oleInPlaceActiveObject.Ok()) if (m_oleInPlaceActiveObject.Ok())
@@ -843,6 +1168,12 @@ void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
event.Skip(); event.Skip();
} }
//---------------------------------------------------------------------------
// wxActiveXContainer::OnKillFocus
//
// Called when the focus is killed on the parent -
// deactivates the activex control
//---------------------------------------------------------------------------
void wxActiveXContainer::OnKillFocus(wxFocusEvent& event) void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
{ {
if (m_oleInPlaceActiveObject.Ok()) if (m_oleInPlaceActiveObject.Ok())
@@ -850,3 +1181,6 @@ void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
event.Skip(); event.Skip();
} }
#endif
// __WINE__

File diff suppressed because it is too large Load Diff