//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ template<class T> bool LatentSpmc<T>::Push(uint frame, const T& item, u32 threadMask) { u32 queueMask = GetQueueMask(); threadMask &= queueMask; for( u32 m=threadMask; m; m &= m - 1 ) { uint thread = LeastSignificantBit(m); eiASSERT( thread < GetQueueCount() ); Queue* queue = GetHeadQueue(thread, frame); if( queue->count >= m_capacity ) {//fail to push, undo the push made to previous queues for( u32 u=threadMask; u && u!= m; u &= u - 1 ) { thread = LeastSignificantBit(u); queue = GetHeadQueue(thread, frame); eiASSERT( queue->count > 0 ); queue->count--; } return false; } else (&queue->storage)[queue->count++] = item; } return true; }
//------------------------------------------------------------------------------ template<class T> bool LatentMpsc<T>::Peek(uint frame, T*& item) { for( uint i=0, end=GetQueueCount(); i!=end; ++i ) { Queue* queue = GetTailQueue(i, frame); if( queue->count ) { item = &(&queue->storage)[queue->count-1]; return true; } } return false; }
template<class T> void LatentMpsc<T>::Pop(uint frame) { for( uint i=0, end=GetQueueCount(); i!=end; ++i ) { Queue* queue = GetTailQueue(i, frame); if( queue->count ) { queue->count--; return; } } eiASSERT( false ); }
//------------------------------------------------------------------------------ template<class T> bool LatentMpsc<T>::Pop(uint frame, T*& items, uint& count) { for( uint i=0, end=GetQueueCount(); i!=end; ++i ) { Queue* queue = GetTailQueue(i, frame); if( queue->count ) { items = &queue->storage; count = queue->count; queue->count = 0; return true; } } return false; }
TakeoffQueueInSim * TakeoffQueuesManager::GetRunwayExitQueue( RunwayExitInSim * pRunwayExit ) { //ASSERT(pRunwayExit); if(!pRunwayExit) return NULL; for(int i = 0 ;i< GetQueueCount() ;i++) { TakeoffQueueInSim * pQueue = GetQueue(i); FlightGroundRouteDirectSegInSim * pDirSeg = pRunwayExit->GetRouteSeg(); FlightGroundRouteDirectSegInSim * pOtherSeg = pDirSeg->GetOppositeSegment(); if( pQueue->GetRunway() == pRunwayExit->GetLogicRunway() && pQueue->IsHaveSegment(pOtherSeg) ) { return pQueue; } } return NULL; }
DWORD CXySubPicQueue::ThreadProc() { SetThreadName(DWORD(-1), "Subtitle Renderer Thread"); SetThreadPriority(m_hThread, THREAD_PRIORITY_ABOVE_NORMAL); bool bAgain = true; for (;;) { DWORD Ret = WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, bAgain ? 0 : INFINITE); bAgain = false; if (Ret == WAIT_TIMEOUT) { ; } else if ((Ret - WAIT_OBJECT_0) != EVENT_TIME) { break; } double fps = m_fps; REFERENCE_TIME rtTimePerFrame = (REFERENCE_TIME)(10000000.0 / fps); REFERENCE_TIME rtNow = UpdateQueue(); int nMaxSubPic = m_nMaxSubPic; CComPtr<ISubPicProvider> pSubPicProvider; GetSubPicProvider(&pSubPicProvider); CComQIPtr<IXyCompatProvider> pXySubPicProvider = pSubPicProvider; if (pXySubPicProvider && SUCCEEDED(pSubPicProvider->Lock())) { for (REFERENCE_TIME rtStart = rtNow; !m_fBreakBuffering && GetQueueCount() < nMaxSubPic; rtStart += rtTimePerFrame) { REFERENCE_TIME rtStop = rtStart + rtTimePerFrame; if (m_rtNow >= rtStart) { if (m_rtNow >= rtStop) { continue; } } if (rtStart >= m_rtNow + 60 * 10000000i64) { // we are already one minute ahead, this should be enough break; } if (m_rtNow > rtStop) { TRACE(_T("BEHIND\n")); } HRESULT hr = pXySubPicProvider->RequestFrame(rtStart, rtStop, INFINITE); if (SUCCEEDED(hr)) { ULONGLONG id; hr = pXySubPicProvider->GetID(&id); if (SUCCEEDED(hr)) { SIZE MaxTextureSize, VirtualSize; POINT VirtualTopLeft; HRESULT hr2; if (SUCCEEDED(hr2 = pSubPicProvider->GetTextureSize(0, MaxTextureSize, VirtualSize, VirtualTopLeft))) { m_pAllocator->SetMaxTextureSize(MaxTextureSize); } if (m_llSubId == id && !m_Queue.IsEmpty()) { // same subtitle as last time CComPtr<ISubPic> pSubPic = m_Queue.GetTail(); pSubPic->SetStop(rtStop); #if SUBPIC_TRACE_LEVEL > 1 CRect r; pSubPic->GetDirtyRect(&r); TRACE(_T("Skip: %f->%f %dx%d\n"), double(pSubPic->GetStart()) / 10000000.0, double(pSubPic->GetStop()) / 10000000.0, r.Width(), r.Height()); #endif continue; } else { CComPtr<ISubPic> pStatic; if (FAILED(m_pAllocator->GetStatic(&pStatic))) { break; } pStatic->SetInverseAlpha(true); hr = RenderTo(pStatic, rtStart, rtStop, fps, true); #if SUBPIC_TRACE_LEVEL > 0 CRect r; pStatic->GetDirtyRect(&r); TRACE(_T("Render: %f->%f %dx%d\n"), double(rtStart) / 10000000.0, double(rtStop) / 10000000.0, r.Width(), r.Height()); #endif if (FAILED(hr)) { break; } CComPtr<ISubPic> pDynamic; if (FAILED(m_pAllocator->AllocDynamic(&pDynamic)) || FAILED(pStatic->CopyTo(pDynamic))) { break; } if (SUCCEEDED(hr2)) { pDynamic->SetVirtualTextureSize(VirtualSize, VirtualTopLeft); } RelativeTo relativeTo; if (SUCCEEDED(pSubPicProvider->GetRelativeTo(0, relativeTo))) { pDynamic->SetRelativeTo(relativeTo); } AppendQueue(pDynamic); m_llSubId = id; bAgain = true; } } } } pSubPicProvider->Unlock(); } if (m_fBreakBuffering) { bAgain = true; CAutoLock cQueueLock(&m_csQueueLock); REFERENCE_TIME rtInvalidate = m_rtInvalidate; POSITION Iter = m_Queue.GetHeadPosition(); while (Iter) { POSITION ThisPos = Iter; ISubPic* pSubPic = m_Queue.GetNext(Iter); REFERENCE_TIME rtStart = pSubPic->GetStart(); REFERENCE_TIME rtStop = pSubPic->GetStop(); if (rtStop > rtInvalidate) { #if SUBPIC_TRACE_LEVEL >= 0 TRACE(_T("Removed subtitle because of invalidation: %f->%f\n"), double(rtStart) / 10000000.0, double(rtStop) / 10000000.0); #endif m_Queue.RemoveAt(ThisPos); continue; } } /* while (GetCount() && GetTail()->GetStop() > rtInvalidate) { if (GetTail()->GetStart() < rtInvalidate) GetTail()->SetStop(rtInvalidate); else { RemoveTail(); } } */ m_fBreakBuffering = false; } } return 0; }
DWORD CSubPicQueue::ThreadProc() { BOOL bDisableAnim = m_bDisableAnim; SetThreadName(DWORD(-1), "Subtitle Renderer Thread"); SetThreadPriority(m_hThread, bDisableAnim ? THREAD_PRIORITY_LOWEST : THREAD_PRIORITY_ABOVE_NORMAL); bool bAgain = true; for (;;) { DWORD Ret = WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, bAgain ? 0 : INFINITE); bAgain = false; if (Ret == WAIT_TIMEOUT) { ; } else if ((Ret - WAIT_OBJECT_0) != EVENT_TIME) { break; } double fps = m_fps; REFERENCE_TIME rtTimePerFrame = (REFERENCE_TIME)(10000000.0 / fps); REFERENCE_TIME rtNow = UpdateQueue(); int nMaxSubPic = m_nMaxSubPic; CComPtr<ISubPicProvider> pSubPicProvider; if (SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider && SUCCEEDED(pSubPicProvider->Lock())) { for (POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps); pos && !m_fBreakBuffering && GetQueueCount() < nMaxSubPic; pos = pSubPicProvider->GetNext(pos)) { REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps); REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps); if (m_rtNow >= rtStart) { if (m_rtNow >= rtStop) { continue; } } if (rtStart >= m_rtNow + 60 * 10000000i64) { // we are already one minute ahead, this should be enough break; } if (rtNow < rtStop) { REFERENCE_TIME rtCurrent = std::max(rtNow, rtStart); bool bIsAnimated = pSubPicProvider->IsAnimated(pos) && !bDisableAnim; while (rtCurrent < rtStop) { SIZE MaxTextureSize, VirtualSize; POINT VirtualTopLeft; HRESULT hr2; if (SUCCEEDED(hr2 = pSubPicProvider->GetTextureSize(pos, MaxTextureSize, VirtualSize, VirtualTopLeft))) { m_pAllocator->SetMaxTextureSize(MaxTextureSize); } CComPtr<ISubPic> pStatic; if (FAILED(m_pAllocator->GetStatic(&pStatic))) { break; } HRESULT hr; if (bIsAnimated) { REFERENCE_TIME rtEndThis = std::min(rtCurrent + rtTimePerFrame, rtStop); hr = RenderTo(pStatic, rtCurrent, rtEndThis, fps, bIsAnimated); pStatic->SetSegmentStart(rtStart); pStatic->SetSegmentStop(rtStop); #if SUBPIC_TRACE_LEVEL > 0 CRect r; pStatic->GetDirtyRect(&r); TRACE(_T("Render: %f->%f %f->%f %dx%d\n"), double(rtCurrent) / 10000000.0, double(rtEndThis) / 10000000.0, double(rtStart) / 10000000.0, double(rtStop) / 10000000.0, r.Width(), r.Height()); #endif rtCurrent = rtEndThis; } else { hr = RenderTo(pStatic, rtStart, rtStop, fps, bIsAnimated); // Non-animated subtitles aren't part of a segment pStatic->SetSegmentStart(0); pStatic->SetSegmentStop(0); rtCurrent = rtStop; } #if SUBPIC_TRACE_LEVEL > 0 if (m_rtNow > rtCurrent) { TRACE(_T("BEHIND\n")); } #endif if (FAILED(hr)) { break; } if (S_OK != hr) { // subpic was probably empty continue; } CComPtr<ISubPic> pDynamic; if (FAILED(m_pAllocator->AllocDynamic(&pDynamic)) || FAILED(pStatic->CopyTo(pDynamic))) { break; } if (SUCCEEDED(hr2)) { pDynamic->SetVirtualTextureSize(VirtualSize, VirtualTopLeft); } RelativeTo relativeTo; if (SUCCEEDED(pSubPicProvider->GetRelativeTo(pos, relativeTo))) { pDynamic->SetRelativeTo(relativeTo); } AppendQueue(pDynamic); bAgain = true; if (GetQueueCount() >= nMaxSubPic) { break; } } } } pSubPicProvider->Unlock(); } if (m_fBreakBuffering) { bAgain = true; CAutoLock cQueueLock(&m_csQueueLock); REFERENCE_TIME rtInvalidate = m_rtInvalidate; POSITION Iter = m_Queue.GetHeadPosition(); while (Iter) { POSITION ThisPos = Iter; ISubPic* pSubPic = m_Queue.GetNext(Iter); REFERENCE_TIME rtStart = pSubPic->GetStart(); REFERENCE_TIME rtStop = pSubPic->GetStop(); REFERENCE_TIME rtSegmentStop = pSubPic->GetSegmentStop(); if (rtSegmentStop > rtInvalidate) { #if SUBPIC_TRACE_LEVEL >= 0 TRACE(_T("Removed subtitle because of invalidation: %f -> %f (%f)\n"), double(rtStart) / 10000000.0, double(rtStop) / 10000000.0, double(rtSegmentStop) / 10000000.0); #endif m_Queue.RemoveAt(ThisPos); continue; } } /* while (GetCount() && GetTail()->GetStop() > rtInvalidate) { if (GetTail()->GetStart() < rtInvalidate) GetTail()->SetStop(rtInvalidate); else { RemoveTail(); } } */ m_fBreakBuffering = false; } } return 0; }
DWORD CSubPicQueue::ThreadProc() { BOOL bDisableAnim = m_bDisableAnim; SetThreadPriority(m_hThread, bDisableAnim ? THREAD_PRIORITY_LOWEST : THREAD_PRIORITY_ABOVE_NORMAL/*THREAD_PRIORITY_BELOW_NORMAL*/); bool bAgain = true; while(1) { DWORD Ret = WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, bAgain ? 0 : INFINITE); bAgain = false; if (Ret == WAIT_TIMEOUT) ; else if ((Ret - WAIT_OBJECT_0) != EVENT_TIME) break; double fps = m_fps; REFERENCE_TIME rtTimePerFrame = max(10000000.0/fps*1.5, 1000000); //1.5 to reduce flick REFERENCE_TIME rtNow = UpdateQueue(); int nMaxSubPic = m_nMaxSubPic; CComPtr<ISubPicProvider> pSubPicProvider; if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider && SUCCEEDED(pSubPicProvider->Lock()) && SUCCEEDED(m_pAllocator->Lock())) { for(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps); pos && !m_fBreakBuffering && GetQueueCount() < (size_t)nMaxSubPic; pos = pSubPicProvider->GetNext(pos)) { REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps); REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps); if(m_rtNow >= rtStart) { // m_fBufferUnderrun = true; if(m_rtNow >= rtStop) continue; } if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough break; if(rtNow < rtStop) { REFERENCE_TIME rtCurrent = max(rtNow, rtStart); bool bIsAnimated = pSubPicProvider->IsAnimated(pos) && !bDisableAnim; while (rtCurrent < rtStop) { SIZE MaxTextureSize, VirtualSize; POINT VirtualTopLeft; HRESULT hr2; if (SUCCEEDED (hr2 = pSubPicProvider->GetTextureSize(pos, MaxTextureSize, VirtualSize, VirtualTopLeft))) m_pAllocator->SetMaxTextureSize(MaxTextureSize); CComPtr<ISubPic> pStatic; if(FAILED(m_pAllocator->GetStatic(&pStatic))) break; HRESULT hr; if (bIsAnimated) { //if (rtCurrent < m_rtNow + rtTimePerFrame) // rtCurrent = min(m_rtNow + rtTimePerFrame, rtStop-1); REFERENCE_TIME rtEndThis = min(rtCurrent + rtTimePerFrame, rtStop); hr = RenderTo(pStatic, rtCurrent, rtEndThis, fps, bIsAnimated); pStatic->SetSegmentStart(rtStart); pStatic->SetSegmentStop(rtStop); #if DSubPicTraceLevel > 0 CRect r; pStatic->GetDirtyRect(&r); TRACE("Render: %f %f %f->%f %f->%f %dx%d\n",m_fps ,(double)rtTimePerFrame/ 10000000.0 , double(rtCurrent) / 10000000.0, double(rtEndThis) / 10000000.0, double(rtStart) / 10000000.0, double(rtStop) / 10000000.0, r.Width(), r.Height()); #endif rtCurrent = rtEndThis; } else { hr = RenderTo(pStatic, rtStart, rtStop, fps, bIsAnimated); rtCurrent = rtStop; } #if DSubPicTraceLevel > 0 if (m_rtNow > rtCurrent) { TRACE("BEHIND\n"); } #endif if(FAILED(hr)) break; if(S_OK != hr) // subpic was probably empty continue; CComPtr<ISubPic> pDynamic; if(FAILED(m_pAllocator->AllocDynamic(&pDynamic)) || FAILED(pStatic->CopyTo(pDynamic))) break; if (SUCCEEDED (hr2)) pDynamic->SetVirtualTextureSize (VirtualSize, VirtualTopLeft); AppendQueue(pDynamic); bAgain = true; if (GetQueueCount() >= (size_t)nMaxSubPic) break; } } } pSubPicProvider->Unlock(); m_pAllocator->Unlock(); } if(m_fBreakBuffering) { bAgain = true; CAutoLock cQueueLock(&m_csQueueLock); REFERENCE_TIME rtInvalidate = m_rtInvalidate; POSITION Iter = m_Queue.GetHeadPosition(); while(Iter) { POSITION ThisPos = Iter; ISubPic *pSubPic = m_Queue.GetNext(Iter); REFERENCE_TIME rtStart = pSubPic->GetStart(); REFERENCE_TIME rtStop = pSubPic->GetStop(); if (rtStop > rtInvalidate) { #if DSubPicTraceLevel >= 0 TRACE(("Removed subtitle because of invalidation: %f->%f\n"), double(rtStart) / 10000000.0, double(rtStop) / 10000000.0); #endif m_Queue.RemoveAt(ThisPos); continue; } } /* while(GetCount() && GetTail()->GetStop() > rtInvalidate) { if(GetTail()->GetStart() < rtInvalidate) GetTail()->SetStop(rtInvalidate); else { RemoveTail(); } } */ m_fBreakBuffering = false; } } return(0); }
void SjMainFrame::CreatePlaybackMenu(SjMenu* playbackMenu, bool createMainMenu) { bool anythingInQueue = GetQueueCount()>0; playbackMenu->Append(IDT_MORE_FROM_CURR_ALBUM); playbackMenu->Enable(IDT_MORE_FROM_CURR_ALBUM, anythingInQueue); playbackMenu->Append(IDT_MORE_FROM_CURR_ARTIST); playbackMenu->Enable(IDT_MORE_FROM_CURR_ARTIST, anythingInQueue); playbackMenu->AppendSeparator(); if( createMainMenu || IsOpAvailable(SJ_OP_PLAYPAUSE) ) { playbackMenu->AppendRadioItem(IDT_PLAY); playbackMenu->Check(IDT_PLAY, m_player.IsPlaying()); playbackMenu->AppendRadioItem(IDT_PAUSE); playbackMenu->Check(IDT_PAUSE, m_player.IsPaused()); playbackMenu->AppendRadioItem(IDT_STOP); playbackMenu->Check(IDT_STOP, m_player.IsStopped()); playbackMenu->AppendCheckItem(IDT_STOP_AFTER_THIS_TRACK); playbackMenu->Check(IDT_STOP_AFTER_THIS_TRACK, m_player.StopAfterThisTrack()); playbackMenu->AppendCheckItem(IDT_STOP_AFTER_EACH_TRACK); playbackMenu->Check(IDT_STOP_AFTER_EACH_TRACK, m_player.StopAfterEachTrack()); } if( createMainMenu || IsOpAvailable(SJ_OP_EDIT_QUEUE) ) { if( !IsOpAvailable(SJ_OP_PLAYPAUSE) ) playbackMenu->AppendSeparator(); playbackMenu->Append(IDT_PREV); playbackMenu->Enable(IDT_PREV, HasPrev()); bool hasNext = HasNextRegardAP(); playbackMenu->Append(IDT_NEXT, GetNextMenuTitle()); playbackMenu->Enable(IDT_NEXT, hasNext); playbackMenu->Append(IDT_FADE_TO_NEXT); playbackMenu->Enable(IDT_FADE_TO_NEXT, hasNext); } if( createMainMenu || IsOpAvailable(SJ_OP_MAIN_VOL) ) { SjMenu* volMenu = new SjMenu(playbackMenu->ShowShortcuts()); volMenu->Append(IDT_MAIN_VOL_UP); volMenu->Append(IDT_MAIN_VOL_DOWN); volMenu->AppendCheckItem(IDT_MAIN_VOL_MUTE); volMenu->Check(IDT_MAIN_VOL_MUTE, m_player.GetMainVolMute()); playbackMenu->Append(0, _("Volume"), volMenu); } if( createMainMenu || IsOpAvailable(SJ_OP_EDIT_QUEUE) || IsOpAvailable(SJ_OP_REPEAT) || IsOpAvailable(SJ_OP_PLAYPAUSE) ) { playbackMenu->AppendSeparator(); if( createMainMenu || IsOpAvailable(SJ_OP_REPEAT) ) { wxString repeatText; // default by SjAccelModule if( m_player.m_queue.GetRepeat()==1 ) repeatText = _("Repeat one"); if( m_player.m_queue.GetRepeat()==2 ) repeatText = _("Repeat all"); playbackMenu->AppendCheckItem(IDT_REPEAT, repeatText); playbackMenu->Check(IDT_REPEAT, m_player.m_queue.GetRepeat()!=0); } if( createMainMenu || IsOpAvailable(SJ_OP_EDIT_QUEUE) ) { playbackMenu->AppendCheckItem(IDT_SHUFFLE); playbackMenu->Check(IDT_SHUFFLE, m_player.m_queue.GetShuffle()); } if( createMainMenu || IsOpAvailable(SJ_OP_EDIT_QUEUE) || IsOpAvailable(SJ_OP_PLAYPAUSE) ) { SjMenu* queueMenu = new SjMenu(playbackMenu->ShowShortcuts()); if( IsOpAvailable(SJ_OP_PLAYPAUSE) ) { queueMenu->AppendCheckItem(IDO_START_PB_ON_ENQUEUE, _("Start playback on first enqueue")); queueMenu->Check(IDO_START_PB_ON_ENQUEUE, (g_accelModule->m_flags&SJ_ACCEL_START_PLAYBACK_ON_ENQUEUE)!=0); } if( IsOpAvailable(SJ_OP_EDIT_QUEUE) ) { queueMenu->AppendCheckItem(IDT_PLAY_NOW_ON_DBL_CLICK); queueMenu->Check(IDT_PLAY_NOW_ON_DBL_CLICK, (g_accelModule->m_flags&SJ_ACCEL_PLAY_NOW_ON_DBL_CLICK)!=0); } playbackMenu->Append(0, _("Queue"), queueMenu); } } }