📄 timeline.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: timeline.cpp,v 1.10.32.1 2004/07/09 02:06:33 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#include "hxcom.h"#include "hlxclib/stdio.h"#include "hxresult.h"#include "hxassert.h"#include "hxtypes.h"#include "ihxpckts.h"#include "hxengin.h"#include "hxfiles.h"#include "hxcore.h"#include "hxprefs.h"#include "hxausvc.h"#include "timeval.h"#include "hxtick.h"#include "hxsched.h"#include "hxmap.h"#include "hxstat.h"#include "timeline.h"#include "hxheap.h"#ifdef _DEBUG#undef HX_THIS_FILE static const char HX_THIS_FILE[] = __FILE__;#endif//#define LOG_MULTIPLE_DEFERRED_TASKS 1// static initializations..#if !defined(HELIX_CONFIG_NOSTATICS)#if defined(_WINDOWS) || defined(_SYMBIAN)CHXMapLongToObj Timeline::m_zTimerMap;#elif defined(_UNIX) || defined (_MACINTOSH) || defined(__TCS__) || defined(_OPENWAVE)CHXMapPtrToPtr Timeline::m_zTimerMap;#endif#else /* #if !defined(HELIX_CONFIG_NOSTATICS) */#include "globals/hxglobals.h"#if defined(_WINDOWS) || defined(_SYMBIAN)typedef CHXMapLongToObj TimelineMapType;typedef HXGlobalMapLongToObj GlobalTimelineMapType;#elif defined(_UNIX) || defined (_MACINTOSH)typedef CHXMapPtrToPtr TimelineMapType;typedef HXGlobalMapPtrToPtr GlobalTimelineMapType;#endifconst TimelineMapType* const Timeline::m_zTimerMap = NULL;#endif /* #if !defined(HELIX_CONFIG_NOSTATICS) */#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */#define MINIMUM_GRANULARITY 55#elif defined(_MACINTOSH)#define MINIMUM_GRANULARITY 20#elif defined(_UNIX) #define MINIMUM_GRANULARITY 20#else#define MINIMUM_GRANULARITY 20#endif#ifdef _MACINTOSH#include "hxmm.h" //for checking if VMULONG32 gTIMELINE_MUTEX=NULL;#define CLOCKSET(c) (c.qType & kTMTaskActive)#endif#ifdef _MACINTOSH#ifdef _CARBONtypedef pascal Handle (*NewHandleSysProcPtr)(Size);CFragConnectionID gInterfaceLibConnID = kInvalidID;NewHandleSysProcPtr gNewHandleSysProc = nil;bool gTriedToInitialize = false;void InitInterfaceLibProcPtrs(){ if (gTriedToInitialize) return; gTriedToInitialize = true; if (gInterfaceLibConnID == kInvalidID) { GetSharedLibrary("\pInterfaceLib", kCompiledCFragArch, kReferenceCFrag, &gInterfaceLibConnID, nil, nil); } if (gInterfaceLibConnID != kInvalidID) { OSErr err = noErr; err = FindSymbol(gInterfaceLibConnID, "\pNewHandleSys", (Ptr*)&gNewHandleSysProc, nil); }}#endif#endif/* * This class was originally written to keep track of time and report the * *current* time to the user. This was the reason that pause, seek and * stuff were implemented. For this it needs to know the user (HXPlayer). * If we wanna use it from other object, the only way would be to pass it * a generic callback. But since IHXCallback's func does not take any * parameter, we cannot pass the *current* time back. * * Since this class will eventually go away, I have made it to work so that * it can be used by HXPlayer and HXScheduler by passing IUnknown. * */Timeline::Timeline(void) : m_ulGranularity (MINIMUM_GRANULARITY) , m_bIsTimerPending (FALSE) , m_bPaused (FALSE) , m_pPlayer (0) , m_pScheduler (0) , m_ulLastCallbackTime (0) , m_bTimerFixup (FALSE)#if defined(_WINDOWS) || defined(_SYMBIAN) , m_uiTimerID (0) , m_uiTimerIDFixup (0)#endif #ifdef _MACINTOSH , m_uppTask(NULL) , m_bUseDeferredTasks(TRUE) , m_pInterruptState(NULL) , m_bAnyCallbackPending(0) , m_bIsQuitting (FALSE)#ifdef THREADS_SUPPORTED , m_pCoreMutex(NULL)#endif#endif{#ifdef _MACINTOSH memset( &m_DeferredTaskStruct, 0, sizeof(m_DeferredTaskStruct) ); memset( &m_tmInfo, 0, sizeof(m_tmInfo) );#endif};Timeline::~Timeline(){ if (m_bIsTimerPending) { Pause(); } m_bIsTimerPending = FALSE; Done(); #ifdef _MACINTOSH if (m_uppTask) {#ifdef _CARBON DisposeTimerUPP(m_uppTask);#else DisposeRoutineDescriptor(m_uppTask);#endif m_uppTask = NULL; } if (m_DeferredTaskStruct.dtAddr != NULL) { // first ensure that the Gestalt handle doesn't think it's // here any more. Handle dtGestaltHandle = nil; Gestalt( kLetInterruptsFinishBeforeQuittingGestalt, (long*)&dtGestaltHandle ); if ( dtGestaltHandle ) { // XXXNH: only look at tasks for this process ProcessSerialNumber psn; GetCurrentProcess(&psn); // zip through and if an entry equals this deferred task, // simply zero it out. We won't worry about shuffling // the handle size at this juncture. long hSize = GetHandleSize( dtGestaltHandle ); GestaltDeferredStruct* currentPtr = (GestaltDeferredStruct*)*dtGestaltHandle; for ( int i = 0; i < hSize / sizeof(GestaltDeferredStruct); i++ ) { unsigned char bSameProcess = FALSE; SameProcess(&(currentPtr[i].psn), &psn, &bSameProcess); if (bSameProcess && currentPtr[i].quitting == &m_bIsQuitting && currentPtr[i].pending == &m_bAnyCallbackPending ) { currentPtr[i].quitting = NULL; currentPtr[i].pending = NULL; } } } #ifdef _CARBON DisposeDeferredTaskUPP(m_DeferredTaskStruct.dtAddr);#else DisposeRoutineDescriptor(m_DeferredTaskStruct.dtAddr);#endif m_DeferredTaskStruct.dtAddr = NULL; } HX_RELEASE(m_pInterruptState);#endif}HX_RESULTTimeline::Init(IUnknown* pUnknown, BOOL bUseDeferredTask){ if (!pUnknown) { return HXR_INVALID_PARAMETER; }#ifdef _MACINTOSH m_bUseDeferredTasks = bUseDeferredTask; if (m_bUseDeferredTasks) {#ifdef _CARBON m_uppTask = NewTimerUPP((TimerProcPtr)MacTimerProc);#else m_uppTask = NewTimerProc(MacTimerProc);#endif m_tmInfo.tmTask.tmAddr = m_uppTask; m_tmInfo.tmRefCon = (long) this; m_tmInfo.tmTask.tmWakeUp = 0L; m_tmInfo.tmTask.tmReserved = 0L; m_DeferredTaskStruct.dtReserved = 0; m_DeferredTaskStruct.dtFlags = 0;#ifdef _CARBON m_DeferredTaskStruct.dtAddr = NewDeferredTaskUPP(Timeline::DeferredTaskProc);#else m_DeferredTaskStruct.dtAddr = NewDeferredTaskProc(Timeline::DeferredTaskProc);#endif m_DeferredTaskStruct.dtParam = (long) this; m_DeferredTaskStruct.qType = dtQType; // Gestalt-based code that remembers potential deferred tasks for emergency removal Handle dtGestaltHandle = nil; OSErr err = Gestalt( kLetInterruptsFinishBeforeQuittingGestalt, (long*)&dtGestaltHandle ); if ( err != noErr ) {#ifdef _CARBON InitInterfaceLibProcPtrs(); if (gNewHandleSysProc) { dtGestaltHandle = (*gNewHandleSysProc)( 0 ); } if (!dtGestaltHandle) { dtGestaltHandle = NewHandle( 0 ); }#else dtGestaltHandle = NewHandleSys( 0 );#endif if ( dtGestaltHandle ) { NewGestaltValue( kLetInterruptsFinishBeforeQuittingGestalt, (long)dtGestaltHandle ); } } if ( dtGestaltHandle ) { GestaltDeferredStruct gds; gds.quitting = &m_bIsQuitting; gds.pending = &m_bAnyCallbackPending; GetCurrentProcess(&(gds.psn)); PtrAndHand( &gds, dtGestaltHandle, sizeof(gds) ); } }#endif /* _MACINTOSH */ HX_RELEASE(m_pScheduler); // Just get the interface for the scheduler; audio services will provide the // player OnTimeSync interface. if (!SUCCEEDED(pUnknown->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler))) { return HXR_INVALID_PARAMETER; //HX_INVALID_OBJECT; } else {#if defined (_MACINTOSH) HX_RELEASE(m_pInterruptState); m_pScheduler->QueryInterface(IID_IHXInterruptState, (void**)&m_pInterruptState);#endif /* _MACINTOSH */ } return HXR_OK;}HX_RESULTTimeline::Pause(void){#if defined(HELIX_CONFIG_NOSTATICS) TimelineMapType& m_zTimerMap = GlobalTimelineMapType::Get(&Timeline::m_zTimerMap);#endif m_bPaused = TRUE; if (!m_bIsTimerPending) { return HXR_OK; } m_bIsTimerPending = FALSE; // Kill the timer for this timeline#if defined(_WINDOWS) || defined(_SYMBIAN) if (!m_bTimerFixup) { // This is the "old code". Execute it just as before the // timerfixup functionality was introduced. HXAsyncTimer::KillTimer( m_uiTimerID ); TimerObjects* pTimerObject = 0; if (m_zTimerMap.Lookup((LONG32) m_uiTimerID, (void*&) pTimerObject)) { if (pTimerObject->m_uiTimer == m_uiTimerID) { m_zTimerMap.RemoveKey((LONG32) m_uiTimerID); delete pTimerObject; } } } else { TimerObjects* pTimerObject = 0; BOOL deletedFlag = FALSE; if (m_uiTimerID) { HXAsyncTimer::KillTimer(m_uiTimerID); if (m_zTimerMap.Lookup((LONG32) m_uiTimerID, (void*&) pTimerObject)) { m_zTimerMap.RemoveKey((LONG32) m_uiTimerID); delete pTimerObject; pTimerObject = NULL; deletedFlag = TRUE; } } if (m_uiTimerIDFixup) { HXAsyncTimer::KillTimer(m_uiTimerIDFixup); if (m_zTimerMap.Lookup((LONG32) m_uiTimerIDFixup, (void*&) pTimerObject)) { m_zTimerMap.RemoveKey((LONG32) m_uiTimerIDFixup); if (deletedFlag == FALSE) delete pTimerObject; pTimerObject = NULL; } } } m_uiTimerID = 0; m_uiTimerIDFixup = 0;#elif defined (_UNIX) || defined(_MACINTOSH) || defined(__TCS__)#ifdef _MACINTOSH if ( m_bUseDeferredTasks && CLOCKSET(m_tmInfo.tmTask) ) { ::RmvTime( (QElemPtr)&m_tmInfo ); m_bAnyCallbackPending = 0; }#endif Timeline* pTimeline; if (m_zTimerMap.Lookup(this, (void*&) pTimeline)) { HX_ASSERT(pTimeline == this); if (pTimeline == this)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -