⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mediactrl.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        src/mac/carbon/mediactrl.cpp
// Purpose:     Built-in Media Backends for Mac
// Author:      Ryan Norton <wxprojects@comcast.net>
// Modified by:
// Created:     11/07/04
// RCS-ID:      $Id: mediactrl.cpp,v 1.28 2006/05/23 11:04:17 ABX Exp $
// Copyright:   (c) 2004-2006 Ryan Norton
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// OK, a casual overseer of this file may wonder why we don't use
// either CreateMovieControl or HIMovieView...
//
// CreateMovieControl
//      1) Need to dispose and create each time a new movie is loaded
//      2) Not that many real advantages
//      3) Progressively buggier in higher OSX versions
//              (see main.c of QTCarbonShell sample for details)
// HIMovieView
//      1) Crashes on destruction in ALL cases on quite a few systems!
//          (With the only real "alternative" is to simply not
//           dispose of it and let it leak...)
//      2) Massive refreshing bugs with its movie controller between
//          movies
//
// At one point we had a complete implementation for CreateMovieControl
// and on my (RN) local copy I had one for HIMovieView - but they
// were simply deemed to be too buggy/unuseful. HIMovieView could
// have been useful as well because it uses OpenGL contexts instead
// of GWorlds. Perhaps someday when someone comes out with some
// ingenious workarounds :).
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#if wxUSE_MEDIACTRL

#include "wx/mediactrl.h"

#ifndef WX_PRECOMP
    #include "wx/log.h"
    #include "wx/timer.h"
#endif

// uma is for wxMacFSSpec
#include "wx/mac/uma.h"

// standard QT stuff
#ifndef __DARWIN__
#include <Movies.h>
#include <Gestalt.h>
#include <QuickTimeComponents.h>
#else
#include <QuickTime/QuickTimeComponents.h>
#endif

//---------------------------------------------------------------------------
// Height and Width of movie controller in the movie control (apple samples)
//---------------------------------------------------------------------------
#define wxMCWIDTH   320
#define wxMCHEIGHT  16

//===========================================================================
//  BACKEND DECLARATIONS
//===========================================================================

//---------------------------------------------------------------------------
//  wxQTMediaBackend
//---------------------------------------------------------------------------

class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
{
public:
    wxQTMediaBackend();
    ~wxQTMediaBackend();

    virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
                                     wxWindowID id,
                                     const wxPoint& pos,
                                     const wxSize& size,
                                     long style,
                                     const wxValidator& validator,
                                     const wxString& name);

    virtual bool Load(const wxString& fileName);
    virtual bool Load(const wxURI& location);

    virtual bool Play();
    virtual bool Pause();
    virtual bool Stop();

    virtual wxMediaState GetState();

    virtual bool SetPosition(wxLongLong where);
    virtual wxLongLong GetPosition();
    virtual wxLongLong GetDuration();

    virtual void Move(int x, int y, int w, int h);
    wxSize GetVideoSize() const;

    virtual double GetPlaybackRate();
    virtual bool SetPlaybackRate(double dRate);

    virtual double GetVolume();
    virtual bool SetVolume(double);

    void Cleanup();
    void FinishLoad();

    virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);

    virtual wxLongLong GetDownloadProgress();
    virtual wxLongLong GetDownloadTotal();

    virtual void MacVisibilityChanged();

    //
    //  ------  Implementation from now on  --------
    //
    bool DoPause();
    bool DoStop();

    void DoLoadBestSize();
    void DoSetControllerVisible(wxMediaCtrlPlayerControls flags);

    wxLongLong GetDataSizeFromStart(TimeValue end);

    Boolean IsQuickTime4Installed();
    void DoNewMovieController();

    static pascal void PPRMProc(
        Movie theMovie, OSErr theErr, void* theRefCon);

    //TODO: Last param actually long - does this work on 64bit machines?
    static pascal Boolean MCFilterProc(MovieController theController,
        short action, void *params, long refCon);

    static pascal OSStatus WindowEventHandler(
        EventHandlerCallRef inHandlerCallRef,
        EventRef inEvent, void *inUserData  );

    wxSize m_bestSize;          // Original movie size
    Movie m_movie;              // Movie instance
    bool m_bPlaying;            // Whether media is playing or not
    class wxTimer* m_timer;     // Timer for streaming the movie
    MovieController m_mc;       // MovieController instance
    wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags

    // Event handlers and UPPs/Callbacks
    EventHandlerRef             m_windowEventHandler;
    EventHandlerUPP             m_windowUPP;

    MoviePrePrerollCompleteUPP  m_preprerollupp;
    MCActionFilterWithRefConUPP m_mcactionupp;

    GWorldPtr m_movieWorld;  //Offscreen movie GWorld

    friend class wxQTMediaEvtHandler;

    DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
};

// helper to hijack background erasing for the QT window
class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
{
public:
    wxQTMediaEvtHandler(wxQTMediaBackend *qtb)
    {
        m_qtb = qtb;

        qtb->m_ctrl->Connect(
            qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
            wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
            NULL, this);
    }

    void OnEraseBackground(wxEraseEvent& event);

private:
    wxQTMediaBackend *m_qtb;

    DECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler)
};

//===========================================================================
//  IMPLEMENTATION
//===========================================================================


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxQTMediaBackend
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)

//Time between timer calls - this is the Apple recommondation to the TCL
//team I believe
#define MOVIE_DELAY 20

//---------------------------------------------------------------------------
//          wxQTMediaLoadTimer
//
//  QT, esp. QT for Windows is very picky about how you go about
//  async loading.  If you were to go through a Windows message loop
//  or a MoviesTask or both and then check the movie load state
//  it would still return 1000 (loading)... even (pre)prerolling doesn't
//  help.  However, making a load timer like this works
//---------------------------------------------------------------------------
class wxQTMediaLoadTimer : public wxTimer
{
public:
    wxQTMediaLoadTimer(wxQTMediaBackend* parent) :
      m_parent(parent) {}

    void Notify()
    {
        ::MCIdle(m_parent->m_mc);

        // kMovieLoadStatePlayable is not enough on MAC:
        // it plays, but IsMovieDone might return true (!)
        // sure we need to wait until kMovieLoadStatePlaythroughOK
        if (::GetMovieLoadState(m_parent->m_movie) >= 20000)
        {
            m_parent->FinishLoad();
            delete this;
        }
    }

protected:
    wxQTMediaBackend *m_parent;     // Backend pointer
};

// --------------------------------------------------------------------------
//          wxQTMediaPlayTimer - Handle Asyncronous Playing
//
// 1) Checks to see if the movie is done, and if not continues
//    streaming the movie
// 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
//    the movie.
// --------------------------------------------------------------------------
class wxQTMediaPlayTimer : public wxTimer
{
public:
    wxQTMediaPlayTimer(wxQTMediaBackend* parent) :
        m_parent(parent) {}

    void Notify()
    {
        //
        //  OK, a little explaining - basically originally
        //  we only called MoviesTask if the movie was actually
        //  playing (not paused or stopped)... this was before
        //  we realized MoviesTask actually handles repainting
        //  of the current frame - so if you were to resize
        //  or something it would previously not redraw that
        //  portion of the movie.
        //
        //  So now we call MoviesTask always so that it repaints
        //  correctly.
        //
        ::MCIdle(m_parent->m_mc);

        //
        //  Handle the stop event - if the movie has reached
        //  the end, notify our handler
        //
        if (::IsMovieDone(m_parent->m_movie))
        {
            if ( m_parent->SendStopEvent() )
            {
                    m_parent->Stop();
                    wxASSERT(::GetMoviesError() == noErr);

                m_parent->QueueFinishEvent();
            }
        }
    }

protected:
    wxQTMediaBackend* m_parent;     // Backend pointer
};


//---------------------------------------------------------------------------
// wxQTMediaBackend Constructor
//
// Sets m_timer to NULL signifying we havn't loaded anything yet
//---------------------------------------------------------------------------
wxQTMediaBackend::wxQTMediaBackend()
    : m_movie(NULL), m_bPlaying(false), m_timer(NULL)
      , m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
      , m_preprerollupp(NULL), m_movieWorld(NULL)
{
}

//---------------------------------------------------------------------------
// wxQTMediaBackend Destructor
//
// 1) Cleans up the QuickTime movie instance
// 2) Decrements the QuickTime reference counter - if this reaches
//    0, QuickTime shuts down
// 3) Decrements the QuickTime Windows Media Layer reference counter -
//    if this reaches 0, QuickTime shuts down the Windows Media Layer
//---------------------------------------------------------------------------
wxQTMediaBackend::~wxQTMediaBackend()
{
    if (m_movie)
        Cleanup();

    // Cleanup for moviecontroller
    if (m_mc)
    {
        // destroy wxQTMediaEvtHandler we pushed on it
        m_ctrl->PopEventHandler(true);
        RemoveEventHandler(m_windowEventHandler);
        DisposeEventHandlerUPP(m_windowUPP);

        // Dispose of the movie controller
        ::DisposeMovieController(m_mc);
        m_mc = NULL;
        DisposeMCActionFilterWithRefConUPP(m_mcactionupp);

        // Dispose of offscreen GWorld
        ::DisposeGWorld(m_movieWorld);
    }

    // Note that ExitMovies() is not necessary...
    ExitMovies();
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::CreateControl
//
// 1) Intializes QuickTime
// 2) Creates the control window
//---------------------------------------------------------------------------
bool wxQTMediaBackend::CreateControl(
    wxControl* ctrl,
    wxWindow* parent,
    wxWindowID id,
    const wxPoint& pos,
    const wxSize& size,
    long style,
    const wxValidator& validator,
    const wxString& name)
{
    if (!IsQuickTime4Installed())
        return false;

    EnterMovies();

    wxMediaCtrl* mediactrl = (wxMediaCtrl*)ctrl;

    //
    // Create window
    // By default wxWindow(s) is created with a border -
    // so we need to get rid of those
    //
    // Since we don't have a child window like most other
    // backends, we don't need wxCLIP_CHILDREN
    //
    if ( !mediactrl->wxControl::Create(
        parent, id, pos, size,
        wxWindow::MacRemoveBordersFromStyle(style),
        validator, name))
    {
        return false;
    }

#if wxUSE_VALIDATORS
    mediactrl->SetValidator(validator);
#endif

    m_ctrl = mediactrl;
    return true;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::IsQuickTime4Installed
//
// Determines whether version 4 of QT is installed
// (Pretty much for Classic only)
//---------------------------------------------------------------------------
Boolean wxQTMediaBackend::IsQuickTime4Installed()
{
    OSErr error;
    long result;

    error = Gestalt(gestaltQuickTime, &result);
    return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::Load (file version)
//
// 1) Get an FSSpec from the Windows path name
// 2) Open the movie
// 3) Obtain the movie instance from the movie resource
// 4) Close the movie resource
// 5) Finish loading
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Load(const wxString& fileName)
{
    if (m_movie)
        Cleanup();

    ::ClearMoviesStickyError(); // clear previous errors so
                                // GetMoviesStickyError is useful

    OSErr err = noErr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -