wxWidgets/samples/flash/flash.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

597 lines
17 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: flash.cpp
// Purpose: Sample showing integration of Flash ActiveX control
// Author: Vadim Zeitlin
// Created: 2009-01-13
// Copyright: (c) 2009 Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
/*
Documentation for embedding Flash into anything other than a web browser is
not easy to find, here is the tech note which provided most of the
information used here: http://www.adobe.com/go/tn_12059
*/
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef __WXMSW__
#error "ActiveX controls are MSW-only"
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/cmdline.h"
#include "wx/filename.h"
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
#include "wx/msw/ole/activex.h"
// we currently use VC-specific extensions in this sample, it could be
// rewritten to avoid them if there is real interest in doing it but compiler
// COM support in MSVC makes the code much simpler to understand
#ifndef __VISUALC__
#error "This sample requires Microsoft Visual C++ compiler COM extensions"
#endif
// import Flash ActiveX control by using its (standard) type library UUID
//
// no_auto_exclude is needed to import IServiceProvider interface defined in
// this type library even though its name conflicts with a standard Windows
// interface with the same name
#import "libid:D27CDB6B-AE6D-11CF-96B8-444553540000" no_auto_exclude
using namespace ShockwaveFlashObjects;
const CLSID CLSID_ShockwaveFlash = __uuidof(ShockwaveFlash);
const IID IID_IShockwaveFlash = __uuidof(IShockwaveFlash);
inline wxString bstr2wx(const _bstr_t& bstr)
{
return wxString(static_cast<const wchar_t *>(bstr));
}
inline _bstr_t wx2bstr(const wxString& str)
{
return _bstr_t(str.wc_str());
}
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// taken from type library
namespace
{
const int FLASH_DISPID_ONREADYSTATECHANGE = -609; // DISPID_ONREADYSTATECHANGE
const int FLASH_DISPID_ONPROGRESS = 0x7a6;
const int FLASH_DISPID_FSCOMMAND = 0x96;
const int FLASH_DISPID_FLASHCALL = 0xc5;
enum FlashState
{
FlashState_Unknown = -1,
FlashState_Loading,
FlashState_Uninitialized,
FlashState_Loaded,
FlashState_Interactive,
FlashState_Complete,
FlashState_Max
};
} // anonymous namespace
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class FlashApp : public wxApp
{
public:
FlashApp() { }
virtual bool OnInit();
virtual void OnInitCmdLine(wxCmdLineParser& parser);
virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
virtual bool OnExceptionInMainLoop();
private:
wxString m_swf;
wxDECLARE_NO_COPY_CLASS(FlashApp);
};
// Define a new frame type: this is going to be our main frame
class FlashFrame : public wxFrame
{
public:
// ctor takes ownership of the pointer which must be non-NULL and opens the
// given SWF file if it's non-empty
FlashFrame(IShockwaveFlash *flash, const wxString& swf);
virtual ~FlashFrame();
void SetMovie(const wxString& movie);
void Play();
void Stop();
private:
enum
{
Flash_Play = 100,
Flash_Get,
Flash_Set,
Flash_Call,
Flash_CallWithArg
};
void OnOpen(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnPlay(wxCommandEvent&) { Play(); }
void OnStop(wxCommandEvent&) { Stop(); }
void OnBack(wxCommandEvent& event);
void OnForward(wxCommandEvent& event);
void OnInfo(wxCommandEvent& event);
void OnVarGet(wxCommandEvent& event);
void OnVarSet(wxCommandEvent& event);
void OnCall(wxCommandEvent& event);
void OnCallWithArg(wxCommandEvent& event);
void OnActiveXEvent(wxActiveXEvent& event);
// give an error message if hr is not S_OK
void CheckFlashCall(HRESULT hr, const char *func);
// return the name of the Flash control state
wxString GetFlashStateString(int state);
// call CallFunction() with a single argument of the type specified by
// argtype or without any arguments if it is empty
void CallFlashFunc(const wxString& argtype,
const wxString& func,
const wxString& arg = wxString());
const IShockwaveFlashPtr m_flash;
wxLog *m_oldLog;
wxString m_swf;
FlashState m_state;
wxTextCtrl *m_varname,
*m_varvalue,
*m_funcname,
*m_funcarg;
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(FlashFrame);
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(FlashFrame, wxFrame)
EVT_MENU(wxID_OPEN, FlashFrame::OnOpen)
EVT_MENU(wxID_EXIT, FlashFrame::OnQuit)
EVT_MENU(wxID_ABOUT, FlashFrame::OnAbout)
EVT_BUTTON(Flash_Play, FlashFrame::OnPlay)
EVT_BUTTON(wxID_STOP, FlashFrame::OnStop)
EVT_BUTTON(wxID_BACKWARD, FlashFrame::OnBack)
EVT_BUTTON(wxID_FORWARD, FlashFrame::OnForward)
EVT_BUTTON(wxID_INFO, FlashFrame::OnInfo)
EVT_BUTTON(Flash_Get, FlashFrame::OnVarGet)
EVT_BUTTON(Flash_Set, FlashFrame::OnVarSet)
EVT_BUTTON(Flash_Call, FlashFrame::OnCall)
EVT_BUTTON(Flash_CallWithArg, FlashFrame::OnCallWithArg)
EVT_ACTIVEX(wxID_ANY, FlashFrame::OnActiveXEvent)
END_EVENT_TABLE()
IMPLEMENT_APP(FlashApp)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
void FlashApp::OnInitCmdLine(wxCmdLineParser& parser)
{
wxApp::OnInitCmdLine(parser);
parser.AddParam("SWF file to play",
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
}
bool FlashApp::OnCmdLineParsed(wxCmdLineParser& parser)
{
if ( parser.GetParamCount() )
m_swf = parser.GetParam(0);
return wxApp::OnCmdLineParsed(parser);
}
bool FlashApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
IShockwaveFlash *flash = NULL;
HRESULT hr = ::CoCreateInstance
(
CLSID_ShockwaveFlash,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShockwaveFlash,
(void **)&flash
);
if ( FAILED(hr) )
{
wxLogSysError(hr, "Failed to create Flash ActiveX control");
return false;
}
new FlashFrame(flash, m_swf);
return true;
}
bool FlashApp::OnExceptionInMainLoop()
{
try
{
throw;
}
catch ( _com_error& ce )
{
wxLogMessage("COM exception: %s", ce.ErrorMessage());
return true;
}
catch ( ... )
{
throw;
}
}
// ----------------------------------------------------------------------------
// main frame creation
// ----------------------------------------------------------------------------
// frame constructor
FlashFrame::FlashFrame(IShockwaveFlash *flash, const wxString& swf)
: wxFrame(NULL, wxID_ANY, "wxWidgets Flash sample"),
m_flash(flash, false /* take ownership */),
m_swf(swf),
m_state(FlashState_Unknown)
{
// set the frame icon
SetIcon(wxICON(sample));
// create the new log target before doing anything with the Flash that
// could result in log messages
wxTextCtrl * const log = new wxTextCtrl(this, wxID_ANY, "",
wxDefaultPosition, wxSize(-1, 100),
wxTE_MULTILINE);
m_oldLog = wxLog::SetActiveTarget(new wxLogTextCtrl(log));
#if wxUSE_MENUS
// create a menu bar
wxMenu *fileMenu = new wxMenu;
fileMenu->Append(wxID_OPEN);
fileMenu->AppendSeparator();
fileMenu->Append(wxID_EXIT);
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(fileMenu, "&File");
menuBar->Append(helpMenu, "&Help");
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
#if wxUSE_STATUSBAR
CreateStatusBar(2);
SetStatusText("Welcome to wxWidgets Flash embedding sample");
SetStatusText("No loaded file", 1);
#endif // wxUSE_STATUSBAR
wxPanel * const panel = new wxPanel(this);
wxSizer * const sizerPanel = new wxBoxSizer(wxVERTICAL);
wxWindow * const activeXParent = new wxWindow(panel, wxID_ANY,
wxDefaultPosition,
wxSize(300, 200));
new wxActiveXContainer(activeXParent, IID_IShockwaveFlash, flash);
if ( !swf.empty() )
SetMovie(swf);
sizerPanel->Add(activeXParent,
wxSizerFlags(1).Expand().Border());
const wxSizerFlags flagsHorz(wxSizerFlags().Centre().HorzBorder());
wxSizer * const sizerBtns = new wxBoxSizer(wxHORIZONTAL);
sizerBtns->Add(new wxButton(panel, wxID_BACKWARD), flagsHorz);
sizerBtns->Add(new wxButton(panel, Flash_Play, "&Play"), flagsHorz);
sizerBtns->Add(new wxButton(panel, wxID_STOP), flagsHorz);
sizerBtns->Add(new wxButton(panel, wxID_FORWARD), flagsHorz);
sizerBtns->AddSpacer(20);
sizerBtns->Add(new wxButton(panel, wxID_INFO), flagsHorz);
sizerPanel->Add(sizerBtns, wxSizerFlags().Center().Border());
wxSizer * const sizerVar = new wxBoxSizer(wxHORIZONTAL);
sizerVar->Add(new wxStaticText(panel, wxID_ANY, "Variable &name:"),
flagsHorz);
m_varname = new wxTextCtrl(panel, wxID_ANY);
sizerVar->Add(m_varname, flagsHorz);
sizerVar->Add(new wxStaticText(panel, wxID_ANY, "&value:"),
flagsHorz);
m_varvalue = new wxTextCtrl(panel, wxID_ANY);
sizerVar->Add(m_varvalue, flagsHorz);
sizerVar->AddSpacer(10);
sizerVar->Add(new wxButton(panel, Flash_Get, "&Get"), flagsHorz);
sizerVar->Add(new wxButton(panel, Flash_Set, "&Set"), flagsHorz);
sizerPanel->Add(sizerVar, wxSizerFlags().Center().Border());
wxSizer * const sizerCall = new wxBoxSizer(wxHORIZONTAL);
sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&Function name:"),
flagsHorz);
m_funcname = new wxTextCtrl(panel, wxID_ANY);
sizerCall->Add(m_funcname, flagsHorz);
sizerCall->Add(new wxButton(panel, Flash_Call, "&Call"), flagsHorz);
sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&argument:"),
flagsHorz);
m_funcarg = new wxTextCtrl(panel, wxID_ANY);
sizerCall->Add(m_funcarg, flagsHorz);
sizerCall->Add(new wxButton(panel, Flash_CallWithArg, "Call &with arg"),
flagsHorz);
sizerPanel->Add(sizerCall, wxSizerFlags().Center().Border());
panel->SetSizer(sizerPanel);
wxSizer * const sizerFrame = new wxBoxSizer(wxVERTICAL);
sizerFrame->Add(panel, wxSizerFlags(2).Expand());
sizerFrame->Add(log, wxSizerFlags(1).Expand());
SetSizerAndFit(sizerFrame);
Show();
m_flash->PutAllowScriptAccess(L"always");
wxLogMessage("Script access changed to \"%s\"",
bstr2wx(m_flash->GetAllowScriptAccess()));
}
FlashFrame::~FlashFrame()
{
delete wxLog::SetActiveTarget(m_oldLog);
}
// ----------------------------------------------------------------------------
// Flash API wrappers
// ----------------------------------------------------------------------------
void FlashFrame::CheckFlashCall(HRESULT hr, const char *func)
{
if ( FAILED(hr) )
{
wxLogSysError(hr, "Call to IShockwaveFlash::%s() failed", func);
}
}
void FlashFrame::CallFlashFunc(const wxString& argtype,
const wxString& func,
const wxString& arg)
{
wxString args;
if ( !argtype.empty() )
{
args = wxString::Format("<%s>%s</%s>", argtype, arg, argtype);
}
// take care with XML formatting: there should be no spaces in it or the
// call would fail!
wxString request = wxString::Format
(
"<invoke name=\"%s\" returntype=\"xml\">"
"<arguments>"
"%s"
"</arguments>"
"</invoke>",
func,
args
);
wxLogMessage("%s(%s) returned \"%s\"",
func, args,
bstr2wx(m_flash->CallFunction(wx2bstr(request))));
}
wxString FlashFrame::GetFlashStateString(int state)
{
static const char *knownStates[] =
{
"Loading", "Uninitialized", "Loaded", "Interactive", "Complete",
};
if ( state >= 0 && state < WXSIZEOF(knownStates) )
return knownStates[state];
return wxString::Format("unknown state (%d)", state);
}
void FlashFrame::SetMovie(const wxString& movie)
{
// Flash doesn't like relative file names
wxFileName fn(movie);
fn.MakeAbsolute();
const wxString swf = fn.GetFullPath();
if ( swf == m_swf )
m_flash->PutMovie(L"");
else
m_swf = swf;
m_flash->PutMovie(m_swf.wc_str());
SetStatusText("Loaded \"" + m_swf + '"', 1);
}
void FlashFrame::Play()
{
CheckFlashCall(m_flash->Play(), "Play");
}
void FlashFrame::Stop()
{
CheckFlashCall(m_flash->Stop(), "Stop");
}
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
void FlashFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
{
wxString swf = wxLoadFileSelector("Flash movie", ".swf", m_swf, this);
if ( swf.empty() )
return;
SetMovie(swf);
}
void FlashFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void FlashFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox("Flash ActiveX control embedding sample\n"
"\n"
"(c) 2009 Vadim Zeitlin",
"About " + GetTitle(),
wxOK | wxICON_INFORMATION,
this);
}
void FlashFrame::OnActiveXEvent(wxActiveXEvent& event)
{
switch ( event.GetDispatchId() )
{
case FLASH_DISPID_ONREADYSTATECHANGE:
{
const int state = event[0].GetInteger();
if ( state != m_state )
{
wxLogMessage("State changed to %s",
GetFlashStateString(state));
if ( state >= 0 && state < FlashState_Max )
m_state = static_cast<FlashState>(state);
else
m_state = FlashState_Unknown;
}
}
break;
case FLASH_DISPID_ONPROGRESS:
wxLogMessage("Progress: %d%%", event[0].GetInteger());
break;
case FLASH_DISPID_FSCOMMAND:
wxLogMessage("Flash command %s(%s)",
event[0].GetString(), event[1].GetString());
break;
case FLASH_DISPID_FLASHCALL:
wxLogMessage("Flash request \"%s\"", event[0].GetString());
break;
default:
wxLogMessage("Unknown event %ld", event.GetDispatchId());
}
event.Skip();
}
void FlashFrame::OnBack(wxCommandEvent& WXUNUSED(event))
{
CheckFlashCall(m_flash->Back(), "Back");
}
void FlashFrame::OnForward(wxCommandEvent& WXUNUSED(event))
{
CheckFlashCall(m_flash->Forward(), "Forward");
}
void FlashFrame::OnInfo(wxCommandEvent& WXUNUSED(event))
{
const int state = m_flash->GetReadyState();
wxString msg = "State: " + GetFlashStateString(state);
if ( state == FlashState_Complete )
{
msg += wxString::Format(", frame: %ld/%ld",
m_flash->GetFrameNum() + 1,
m_flash->GetTotalFrames());
}
if ( m_flash->IsPlaying() )
msg += ", playing";
wxLogMessage("%s", msg);
}
void FlashFrame::OnVarGet(wxCommandEvent& WXUNUSED(event))
{
m_varvalue->SetValue(bstr2wx(
m_flash->GetVariable(wx2bstr(m_varname->GetValue()))));
}
void FlashFrame::OnVarSet(wxCommandEvent& WXUNUSED(event))
{
m_flash->SetVariable(wx2bstr(m_varname->GetValue()),
wx2bstr(m_varvalue->GetValue()));
}
void FlashFrame::OnCall(wxCommandEvent& WXUNUSED(event))
{
CallFlashFunc("", m_funcname->GetValue());
}
void FlashFrame::OnCallWithArg(wxCommandEvent& WXUNUSED(event))
{
CallFlashFunc("string", m_funcname->GetValue(), m_funcarg->GetValue());
}