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

📄 mediactrl.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    short movieResFile;
    FSSpec sfFile;

    wxMacFilename2FSSpec( fileName, &sfFile );
    if (OpenMovieFile( &sfFile, &movieResFile, fsRdPerm ) != noErr)
        return false;

    short movieResID = 0;
    Str255 movieName;

    err = NewMovieFromFile(
        &m_movie,
        movieResFile,
        &movieResID,
        movieName,
        newMovieActive,
        NULL); // wasChanged

    //
    // check GetMoviesStickyError() because it may not find the
    // proper codec and play black video and other strange effects,
    // not to mention mess up the dynamic backend loading scheme
    // of wxMediaCtrl - so it just does what the QuickTime player does
    //
    if (err == noErr && ::GetMoviesStickyError() == noErr)
    {
        ::CloseMovieFile(movieResFile);

        // Create movie controller/control
        DoNewMovieController();

        FinishLoad();
        return true;
    }

    return false;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::Load (URL Version)
//
// 1) Build an escaped URI from location
// 2) Create a handle to store the URI string
// 3) Put the URI string inside the handle
// 4) Make a QuickTime URL data ref from the handle with the URI in it
// 5) Clean up the URI string handle
// 6) Do some prerolling
// 7) Finish Loading
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Load(const wxURI& location)
{
    if (m_movie)
        Cleanup();

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

    wxString theURI = location.BuildURI();
    OSErr err;

    size_t len;
    const char* theURIString;

#if wxUSE_UNICODE
    wxCharBuffer buf = wxConvLocal.cWC2MB(theURI, theURI.length(), &len);
    theURIString = buf;
#else
    theURIString = theURI;
    len = theURI.length();
#endif

    Handle theHandle = ::NewHandleClear(len + 1);
    wxASSERT(theHandle);

    ::BlockMoveData(theURIString, *theHandle, len + 1);

    // create the movie from the handle that refers to the URI
    err = ::NewMovieFromDataRef(
        &m_movie,
        newMovieActive | newMovieAsyncOK /* | newMovieIdleImportOK*/,
        NULL, theHandle,
        URLDataHandlerSubType);

    ::DisposeHandle(theHandle);

    if (err == noErr && ::GetMoviesStickyError() == noErr)
    {
        // Movie controller resets prerolling, so we must create first
        DoNewMovieController();

        long timeNow;
        Fixed playRate;

        timeNow = ::GetMovieTime(m_movie, NULL);
        wxASSERT(::GetMoviesError() == noErr);

        playRate = ::GetMoviePreferredRate(m_movie);
        wxASSERT(::GetMoviesError() == noErr);

        //
        //  Note that the callback here is optional,
        //  but without it PrePrerollMovie can be buggy
        //  (see Apple ml).  Also, some may wonder
        //  why we need this at all - this is because
        //  Apple docs say QuickTime streamed movies
        //  require it if you don't use a Movie Controller,
        //  which we don't by default.
        //
        m_preprerollupp =
            NewMoviePrePrerollCompleteUPP( wxQTMediaBackend::PPRMProc );
        ::PrePrerollMovie( m_movie, timeNow, playRate,
                           m_preprerollupp, (void*)this);

        return true;
    }

    return false;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::DoNewMovieController
//
// Attaches movie to moviecontroller or creates moviecontroller
// if not created yet
//---------------------------------------------------------------------------
void wxQTMediaBackend::DoNewMovieController()
{
    if (!m_mc)
    {
        // Get top level window ref for some mac functions
        WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef();

        // MovieController not set up yet, so we need to create a new one.
        // You have to pass a valid movie to NewMovieController, evidently
        ::SetMovieGWorld(m_movie,
                       (CGrafPtr) GetWindowPort(wrTLW),
                       NULL);
        wxASSERT(::GetMoviesError() == noErr);

        Rect bounds = wxMacGetBoundsForControl(
            m_ctrl,
            m_ctrl->GetPosition(),
            m_ctrl->GetSize());

        m_mc = ::NewMovieController(
            m_movie, &bounds,
            mcTopLeftMovie | mcNotVisible /* | mcWithFrame */ );
        wxASSERT(::GetMoviesError() == noErr);

        ::MCDoAction(m_mc, 32, (void*)true); // mcActionSetKeysEnabled
        wxASSERT(::GetMoviesError() == noErr);

        // Setup a callback so we can tell when the user presses
        // play on the player controls
        m_mcactionupp =
            NewMCActionFilterWithRefConUPP( wxQTMediaBackend::MCFilterProc );
        ::MCSetActionFilterWithRefCon( m_mc, m_mcactionupp, (long)this );
        wxASSERT(::GetMoviesError() == noErr);

        // Part of a suggestion from Greg Hazel to repaint movie when idle
        m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this));

        // Create offscreen GWorld for where to "show" when window is hidden
        Rect worldRect;
        worldRect.left = worldRect.top = 0;
        worldRect.right = worldRect.bottom = 1;
        ::NewGWorld(&m_movieWorld, 0, &worldRect, NULL, NULL, 0);

        // Catch window messages:
        // if we do not do this and if the user clicks the play
        // button on the controller, for instance, nothing will happen...
        EventTypeSpec theWindowEventTypes[] =
        {
            { kEventClassMouse,     kEventMouseDown },
            { kEventClassMouse,     kEventMouseUp },
            { kEventClassMouse,     kEventMouseDragged },
            { kEventClassKeyboard,  kEventRawKeyDown },
            { kEventClassKeyboard,  kEventRawKeyRepeat },
            { kEventClassKeyboard,  kEventRawKeyUp },
            { kEventClassWindow,    kEventWindowUpdate },
            { kEventClassWindow,    kEventWindowActivated },
            { kEventClassWindow,    kEventWindowDeactivated }
        };
        m_windowUPP =
            NewEventHandlerUPP( wxQTMediaBackend::WindowEventHandler );
        InstallWindowEventHandler(
            wrTLW,
            m_windowUPP,
            GetEventTypeCount( theWindowEventTypes ), theWindowEventTypes,
            this,
            &m_windowEventHandler );
    }
    else
    {
        // MovieController already created:
        // Just change the movie in it and we're good to go
        Point thePoint;
        thePoint.h = thePoint.v = 0;
        ::MCSetMovie(m_mc, m_movie,
              (WindowRef)m_ctrl->MacGetTopLevelWindowRef(),
              thePoint);
        wxASSERT(::GetMoviesError() == noErr);
    }
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::FinishLoad
//
// Performs operations after a movie ready to play/loaded.
//---------------------------------------------------------------------------
void wxQTMediaBackend::FinishLoad()
{
    // Dispose of the PrePrerollMovieUPP if we used it
    DisposeMoviePrePrerollCompleteUPP(m_preprerollupp);

    // get the real size of the movie
    DoLoadBestSize();

    // show the player controls if the user wants to
    if (m_interfaceflags)
        DoSetControllerVisible(m_interfaceflags);

    // we want millisecond precision
    ::SetMovieTimeScale(m_movie, 1000);
    wxASSERT(::GetMoviesError() == noErr);

    // start movie progress timer
    m_timer = new wxQTMediaPlayTimer(this);
    wxASSERT(m_timer);
    m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);

    // send loaded event and refresh size
    NotifyMovieLoaded();
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::DoLoadBestSize
//
// Sets the best size of the control from the real size of the movie
//---------------------------------------------------------------------------
void wxQTMediaBackend::DoLoadBestSize()
{
    // get the real size of the movie
    Rect outRect;
    ::GetMovieNaturalBoundsRect(m_movie, &outRect);
    wxASSERT(::GetMoviesError() == noErr);

    // determine best size
    m_bestSize.x = outRect.right - outRect.left;
    m_bestSize.y = outRect.bottom - outRect.top;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::Play
//
// Start the QT movie
// (Apple recommends mcActionPrerollAndPlay but that's QT 4.1+)
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Play()
{
    Fixed fixRate = (Fixed) (wxQTMediaBackend::GetPlaybackRate() * 0x10000);
    if (!fixRate)
        fixRate = ::GetMoviePreferredRate(m_movie);

    wxASSERT(fixRate != 0);

    if (!m_bPlaying)
        ::MCDoAction( m_mc, 8 /* mcActionPlay */, (void*) fixRate);

    bool result = (::GetMoviesError() == noErr);
    if (result)
    {
        m_bPlaying = true;
        QueuePlayEvent();
    }

    return result;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::Pause
//
// Stop the movie
//---------------------------------------------------------------------------
bool wxQTMediaBackend::DoPause()
{
    // Stop the movie A.K.A. ::StopMovie(m_movie);
    if (m_bPlaying)
    {
        ::MCDoAction( m_mc, 8 /*mcActionPlay*/,  (void *) 0);
        m_bPlaying = false;
        return ::GetMoviesError() == noErr;
    }

    // already paused
    return true;
}

bool wxQTMediaBackend::Pause()
{
    bool bSuccess = DoPause();
    if (bSuccess)
        this->QueuePauseEvent();

    return bSuccess;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::Stop
//
// 1) Stop the movie
// 2) Seek to the beginning of the movie
//---------------------------------------------------------------------------
bool wxQTMediaBackend::DoStop()
{
    if (!wxQTMediaBackend::DoPause())
        return false;

    ::GoToBeginningOfMovie(m_movie);
    return ::GetMoviesError() == noErr;
}

bool wxQTMediaBackend::Stop()
{
    bool bSuccess = DoStop();
    if (bSuccess)
        QueueStopEvent();

    return bSuccess;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::GetPlaybackRate
//
// 1) Get the movie playback rate from ::GetMovieRate
//---------------------------------------------------------------------------
double wxQTMediaBackend::GetPlaybackRate()
{
    return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::SetPlaybackRate
//
// 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
//---------------------------------------------------------------------------
bool wxQTMediaBackend::SetPlaybackRate(double dRate)
{
    ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
    return ::GetMoviesError() == noErr;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::SetPosition
//
// 1) Create a time record struct (TimeRecord) with appropriate values
// 2) Pass struct to SetMovieTime
//---------------------------------------------------------------------------
bool wxQTMediaBackend::SetPosition(wxLongLong where)
{
    TimeRecord theTimeRecord;
    memset(&theTimeRecord, 0, sizeof(TimeRecord));
    theTimeRecord.value.lo = where.GetValue();
    theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
    theTimeRecord.base = ::GetMovieTimeBase(m_movie);
    ::SetMovieTime(m_movie, &theTimeRecord);

    if (::GetMoviesError() != noErr)
        return false;

    return true;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::GetPosition
//
// Calls GetMovieTime
//---------------------------------------------------------------------------
wxLongLong wxQTMediaBackend::GetPosition()
{
    return ::GetMovieTime(m_movie, NULL);
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::GetVolume
//
// Gets the volume through GetMovieVolume - which returns a 16 bit short -
//
// +--------+--------+
// +   (1)  +   (2)  +
// +--------+--------+
//
// (1) first 8 bits are value before decimal
// (2) second 8 bits are value after decimal
//
// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
// 1 (full gain and sound)
//---------------------------------------------------------------------------
double wxQTMediaBackend::GetVolume()
{
    short sVolume = ::GetMovieVolume(m_movie);

    if (sVolume & (128 << 8)) //negative - no sound
        return 0.0;

    return sVolume / 256.0;
}

//---------------------------------------------------------------------------
// wxQTMediaBackend::SetVolume
//
// Sets the volume through SetMovieVolume - which takes a 16 bit short -
//
// +--------+--------+
// +   (1)  +   (2)  +

⌨️ 快捷键说明

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