static OSStatus VolumesChanged( EventHandlerCallRef ref, EventRef event, void *p ) { MemoryCardDriverThreaded_MacOSX *driver = (MemoryCardDriverThreaded_MacOSX *)p; LockMut( driver->m_ChangedLock ); driver->m_bChanged = true; return eventNotHandledErr; // let others do something }
bool BackgroundLoader::IsCacheFileFinished( const CString &sFile, CString &sActualPath ) { if( !g_bEnableBackgroundLoading ) { sActualPath = sFile; return true; } LockMut( m_Mutex ); if( sFile == "" ) { sActualPath = ""; return true; } map<CString,int>::iterator it; it = m_FinishedRequests.find( sFile ); if( it == m_FinishedRequests.end() ) return false; LOG->Trace("XXX: %s finished (%i)", sFile.c_str(), it->second); if( g_bWriteToCache ) sActualPath = GetCachePath( sFile ); else sActualPath = sFile; return true; }
void InputFilter::ButtonPressed( const DeviceInput &di ) { LockMut(*queuemutex); if( di.ts.IsZero() ) LOG->Warn( "InputFilter::ButtonPressed: zero timestamp is invalid" ); ASSERT_M( di.device < NUM_InputDevice, ssprintf("Invalid device %i", di.device) ); ASSERT_M( di.button < NUM_DeviceButton, ssprintf("Invalid button %i", di.button) ); ButtonState &bs = GetButtonState( di ); // Flush any delayed input, like Update() (in case Update() isn't being called). RageTimer now; CheckButtonChange( bs, di, now ); bs.m_DeviceInput = di; bool Down = di.bDown; if( bs.m_BeingHeld != Down ) { bs.m_BeingHeld = Down; bs.m_BeingHeldTime = di.ts; } // Try to report presses immediately. MakeButtonStateList( g_CurrentState ); CheckButtonChange( bs, di, now ); }
bool VirtualMemoryManager::EnsureFreeMemory(size_t size) { if(!inited) return false; LockMut(vmemMutex); MEMORYSTATUS ms; GlobalMemoryStatus(&ms); while(ms.dwAvailPhys < size) { if(LOG && logging) LOG->Trace("Freeing memory: need %i, have %i", size, ms.dwAvailPhys); if(!DecommitLRU()) { if(LOG) LOG->Trace("VMem error: No pages left to free while reserving memory"); return false; } } return true; }
void RageFileManager::GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo ) { LockMut( *g_Mutex ); NormalizePath( sPath ); for( unsigned i = 0; i < g_Drivers.size(); ++i ) { LoadedDriver &ld = g_Drivers[i]; const CString p = ld.GetPath( sPath ); if( p.size() == 0 ) continue; const unsigned OldStart = AddTo.size(); g_Drivers[i].driver->GetDirListing( p, AddTo, bOnlyDirs, bReturnPathToo ); /* If returning the path, prepend the mountpoint name to the files this driver returned. */ if( bReturnPathToo ) for( unsigned j = OldStart; j < AddTo.size(); ++j ) AddTo[j] = ld.MountPoint + AddTo[j]; } /* More than one driver might return the same file. Remove duplicates (case- * insensitively). */ sort( AddTo.begin(), AddTo.end(), ilt ); CStringArray::iterator it = unique( AddTo.begin(), AddTo.end(), ieq ); AddTo.erase(it, AddTo.end()); }
void RageFileManager::Unmount( CString Type, CString Root, CString MountPoint ) { LockMut( *g_Mutex ); FixSlashesInPlace( Root ); FixSlashesInPlace( MountPoint ); if( MountPoint.size() && MountPoint.Right(1) != "/" ) MountPoint += '/'; for( unsigned i = 0; i < g_Drivers.size(); ++i ) { if( g_Drivers[i].Type.CompareNoCase( Type ) ) continue; if( g_Drivers[i].Root.CompareNoCase( Root ) ) continue; if( g_Drivers[i].MountPoint.CompareNoCase( MountPoint ) ) continue; delete g_Drivers[i].driver; g_Drivers.erase( g_Drivers.begin()+i ); } g_Mountpoints->LoadFromDrivers( g_Drivers ); }
RageFileObj *RageFileDriverMem::Open( const CString &sPath, int mode, RageFile &p, int &err ) { LockMut(m_Mutex); if( mode == RageFile::WRITE ) { /* If the file exists, delete it. */ Remove( sPath ); RageFileObjMemFile *pFile = new RageFileObjMemFile; m_Files.push_back( pFile ); FDB->AddFile( sPath, 0, 0, pFile ); return new RageFileObjMem( pFile, p ); } RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath ); if( pFile == NULL ) { err = ENOENT; return NULL; } return new RageFileObjMem( pFile, p ); }
void RageSound_Generic_Software::StopMixing( RageSoundBase *snd ) { /* Lock, to make sure the decoder thread isn't running on this sound while we do this. */ LockMut( m_Mutex ); /* Find the sound. */ unsigned i; for( i = 0; i < ARRAYSIZE(sounds); ++i ) if( !sounds[i].available && sounds[i].snd == snd ) break; if( i == ARRAYSIZE(sounds) ) { LOG->Trace( "not stopping a sound because it's not playing" ); return; } /* If we're already in STOPPED, there's nothing to do. */ if( sounds[i].state == sound::STOPPED ) { LOG->Trace( "not stopping a sound because it's already in STOPPED" ); return; } // LOG->Trace("StopMixing: set %p (%s) to HALTING", sounds[i].snd, sounds[i].snd->GetLoadedFilePath().c_str()); /* Tell the mixing thread to flush the buffer. We don't have to worry about * the decoding thread, since we've locked m_Mutex. */ sounds[i].state = sound::HALTING; /* Invalidate the snd pointer to guarantee we don't make any further references to * it. Once this call returns, the sound may no longer exist. */ sounds[i].snd = NULL; // LOG->Trace("end StopMixing"); }
void InputFilter::ButtonPressed( DeviceInput di, bool Down ) { LockMut(*queuemutex); if( di.ts.IsZero() ) LOG->Warn( "InputFilter::ButtonPressed: zero timestamp is invalid" ); if( di.device >= NUM_INPUT_DEVICES ) { LOG->Warn( "Invalid device %i,%i", di.device, NUM_INPUT_DEVICES ); return; } if( di.button >= GetNumDeviceButtons(di.device) ) { LOG->Warn( "Invalid button %i,%i", di.button, GetNumDeviceButtons(di.device) ); return; } ButtonState &bs = m_ButtonState[di.device][di.button]; RageTimer now; CheckButtonChange( bs, di, now ); if( bs.m_BeingHeld != Down ) { bs.m_BeingHeld = Down; bs.m_BeingHeldTime = di.ts; } /* Try to report presses immediately. */ CheckButtonChange( bs, di, now ); }
void RageThread::Create( int (*fn)(void *), void *data ) { /* Don't create a thread that's already running: */ ASSERT( m_pSlot == NULL ); InitThreads(); /* Lock unused slots, so nothing else uses our slot before we mark it used. */ LockMut(g_ThreadSlotsLock); int slotno = FindEmptyThreadSlot(); m_pSlot = &g_ThreadSlots[slotno]; if( name == "" ) { if( LOG ) LOG->Warn("Created a thread without naming it first."); /* If you don't name it, I will: */ strcpy( m_pSlot->name, "Joe" ); } else { strcpy( m_pSlot->name, name.c_str() ); } if( LOG ) LOG->Trace( "Starting thread: %s", name.c_str() ); sprintf( m_pSlot->ThreadFormattedOutput, "Thread: %s", name.c_str() ); /* Start a thread using our own startup function. We pass the id to fill in, * to make sure it's set before the thread actually starts. (Otherwise, early * checkpoints might not have a completely set-up thread slot.) */ m_pSlot->pImpl = MakeThread( fn, data, &m_pSlot->id ); }
void InputHandler_MacOSX_HID::DeviceAdded( void *refCon, io_iterator_t ) { InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; LockMut( This->m_ChangeLock ); This->m_bChanged = true; }
void RageSoundDriver_ALSA9::StopMixing(RageSoundBase *snd) { /* Lock, to make sure the decoder thread isn't running on this sound while we do this. */ LockMut( m_Mutex ); ASSERT(snd != NULL); unsigned i; for( i = 0; i < stream_pool.size(); ++i ) if(stream_pool[i]->snd == snd) break; if( i == stream_pool.size() ) { LOG->Trace("not stopping a sound because it's not playing"); return; } /* FLUSHING tells the mixer thread to release the stream once str->flush_bufs * buffers have been flushed. */ stream_pool[i]->state = stream_pool[i]->FLUSHING; /* Flush two buffers worth of data. */ stream_pool[i]->flush_pos = stream_pool[i]->pcm->GetPlayPos(); /* This function is called externally (by RageSoundBase) to stop immediately. * We need to prevent SoundStopped from being called; it should only be * called when we stop implicitely at the end of a sound. Set snd to NULL. */ stream_pool[i]->snd = NULL; }
void VirtualMemoryManager::Unlock(void *ptr) { if(!inited) return; LockMut(vmemMutex); // check that the address is within the virtual address bounds if((DWORD)ptr < baseAddress || (DWORD)ptr >= baseAddress + (totalPages * pageSize)) { return; } // find the page(s) to free DWORD offset = (DWORD)ptr - baseAddress; unsigned long pageIndex = offset / pageSize; if(pages[pageIndex].headPage == -1) { return; } pageIndex = pages[pageIndex].headPage; unsigned long endPage = pageIndex + pages[pageIndex].sizeInPages; for(unsigned long i = pageIndex; i < endPage; i++) { pages[i].locked = false; } }
RageFileBasic *RageFileDriverMem::Open( const CString &sPath, int mode, int &err ) { LockMut(m_Mutex); if( mode == RageFile::WRITE ) { /* If the file exists, delete it. */ Remove( sPath ); RageFileObjMemFile *pFile = new RageFileObjMemFile; /* Add one reference, representing the file in the filesystem. */ RageFileObjMemFile::AddReference( pFile ); m_Files.push_back( pFile ); FDB->AddFile( sPath, 0, 0, pFile ); return new RageFileObjMem( pFile ); } RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath ); if( pFile == NULL ) { err = ENOENT; return NULL; } return new RageFileObjMem( pFile ); }
bool RageFileDriverMem::Remove( const CString &sPath ) { LockMut(m_Mutex); RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath ); if( pFile == NULL ) return false; /* Unregister the file. */ FDB->DelFile( sPath ); vector<RageFileObjMemFile *>::iterator it = find( m_Files.begin(), m_Files.end(), pFile ); ASSERT( it != m_Files.end() ); m_Files.erase( it ); pFile->m_Mutex.Lock(); if( pFile->m_iRefs ) { /* The file is in use. The last RageFileObjMem dtor will delete it. */ pFile->m_bDeleted = true; pFile->m_Mutex.Unlock(); } else { pFile->m_Mutex.Unlock(); delete pFile; } return true; }
struct tm *my_localtime_r( const time_t *timep, struct tm *result ) { static RageMutex mut("my_localtime_r"); LockMut(mut); *result = *localtime( timep ); return result; }
bool ArchHooks::AppFocusChanged() { LockMut( g_Mutex ); bool bFocusChanged = m_bFocusChanged; m_bFocusChanged = false; return bFocusChanged; }
bool ArchHooks::GetAndClearToggleWindowed() { LockMut( g_Mutex ); bool bToggle = g_bToggleWindowed; g_bToggleWindowed = false; return bToggle; }
void RemoveReference( const RageFileObj *obj ) { LockMut( *g_Mutex ); FileReferences::iterator it = g_Refs.find( obj ); ASSERT_M( it != g_Refs.end(), ssprintf( "RemoveReference: Missing reference (%s)", obj->GetDisplayPath().c_str() ) ); g_Refs.erase( it ); }
bool RageSound::SetPositionFrames( int iFrames ) { LockMut( m_Mutex ); if( m_pSource == NULL ) { LOG->Warn( "RageSound::SetPositionFrames(%d): sound not loaded", iFrames ); return false; } { /* "m_iDecodePosition" records the number of frames we've output to the * speaker. If the rate isn't 1.0, this will be different from the * position in the sound data itself. For example, if we're playing * at 0.5x, and we're seeking to the 10th frame, we would have actually * played 20 frames, and it's the number of real speaker frames that * "m_iDecodePosition" represents. */ const int iScaledFrames = int( iFrames / GetPlaybackRate() ); /* If we're already there, don't do anything. */ if( m_iDecodePosition == iScaledFrames ) return true; m_iStoppedPosition = m_iDecodePosition = iScaledFrames; } /* The position we're going to seek the input stream to. We have * to do this in floating point to avoid overflow. */ int ms = int( float(iFrames) * 1000.f / samplerate() ); ms = max(ms, 0); m_DataBuffer.clear(); int ret; if( m_Param.AccurateSync ) ret = m_pSource->SetPosition_Accurate(ms); else ret = m_pSource->SetPosition_Fast(ms); if(ret == -1) { /* XXX untested */ Fail( m_pSource->GetError() ); return false; /* failed */ } if(ret == 0 && ms != 0) { /* We were told to seek somewhere, and we got 0 instead, which means * we passed EOF. This could be a truncated file or invalid data. */ LOG->Warn("SetPositionFrames: %i ms is beyond EOF in %s", ms, GetLoadedFilePath().c_str()); return false; /* failed */ } return true; }
void MessageManager::Unsubscribe( IMessageSubscriber* pSubscriber, const RString& sMessage ) { LockMut(g_Mutex); SubscribersSet& subs = g_MessageToSubscribers[sMessage]; SubscribersSet::iterator iter = subs.find(pSubscriber); ASSERT( iter != subs.end() ); subs.erase( iter ); }
void RageLog::Write( int where, const RString &sLine ) { LockMut( *g_Mutex ); const char *const sWarningSeparator = "/////////////////////////////////////////"; vector<RString> asLines; split( sLine, "\n", asLines, false ); if( where & WRITE_LOUD ) { if( m_bLogToDisk && g_fileLog->IsOpen() ) g_fileLog->PutLine( sWarningSeparator ); puts( sWarningSeparator ); } RString sTimestamp = SecondsToMMSSMsMsMs( RageTimer::GetTimeSinceStart() ) + ": "; RString sWarning; if( where & WRITE_LOUD ) sWarning = "WARNING: "; for( unsigned i = 0; i < asLines.size(); ++i ) { RString &sStr = asLines[i]; if( sWarning.size() ) sStr.insert( 0, sWarning ); if( m_bShowLogOutput || (where&WRITE_TO_INFO) ) puts(sStr); //fputws( (const wchar_t *)sStr.c_str(), stdout ); if( where & WRITE_TO_INFO ) AddToInfo( sStr ); if( m_bLogToDisk && (where&WRITE_TO_INFO) && g_fileInfo->IsOpen() ) g_fileInfo->PutLine( sStr ); if( m_bUserLogToDisk && (where&WRITE_TO_USER_LOG) && g_fileUserLog->IsOpen() ) g_fileUserLog->PutLine( sStr ); /* Add a timestamp to log.txt and RecentLogs, but not the rest of info.txt * and stdout. */ sStr.insert( 0, sTimestamp ); if(where & WRITE_TO_TIME) g_fileTimeLog->PutLine(sStr); AddToRecentLogs( sStr ); if( m_bLogToDisk && g_fileLog->IsOpen() ) g_fileLog->PutLine( sStr ); } if( where & WRITE_LOUD ) { if( m_bLogToDisk && g_fileLog->IsOpen() && (where & WRITE_LOUD) ) g_fileLog->PutLine( sWarningSeparator ); puts( sWarningSeparator ); } if( m_bFlush || (where & WRITE_TO_INFO) ) Flush(); }
bool VirtualMemoryManager::DecommitLRU() { if(!inited) return false; LockMut(vmemMutex); // choose random LRU pageLRU = rand() % totalPages; for(unsigned long i = 0; i < totalPages; i++) { unsigned long index = (pageLRU + i) % totalPages; if(index == 0) index++; if(pages[index].headPage == index && pages[index].committed && !pages[index].locked) // this is a head page { DWORD addr = pages[index].startAddress; unsigned long size = pages[index].sizeInPages; // decommit this page // write to the page file if(SetFilePointer(vmemFile, addr - baseAddress, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { if(LOG) LOG->Trace("Vmem error: could not write to page file"); return false; } DWORD written; WriteFile(vmemFile, (LPCVOID)addr, pages[index].sizeInBytes, &written, NULL); // reset the page data if(LOG && logging) LOG->Trace("Swapping out pages %i to %i", index, index + size - 1); for(unsigned long j = index; j < index + size; j++) { pages[j].committed = false; } if(VirtualFree((LPVOID)addr, pages[index].sizeInBytes, MEM_DECOMMIT) == 0) { return false; } pageLRU = (pageLRU + pages[index].sizeInPages) % totalPages; return true; } } return false; }
SetupMainThread() { LockMut(g_ThreadSlotsLock); int slot = FindEmptyThreadSlot(); strcpy( g_ThreadSlots[slot].name, "Main thread" ); sprintf( g_ThreadSlots[slot].ThreadFormattedOutput, "Thread: %s", g_ThreadSlots[slot].name ); g_ThreadSlots[slot].id = RageThread::GetCurrentThreadID(); g_ThreadSlots[slot].pImpl = MakeThisThread(); }
bool RageFileManager::IsMounted( CString MountPoint ) { LockMut( *g_Mutex ); for( unsigned i = 0; i < g_Drivers.size(); ++i ) if( !g_Drivers[i].MountPoint.CompareNoCase( MountPoint ) ) return true; return false; }
void InputHandler_MacOSX_HID::DeviceChanged( void *refCon, io_service_t service, natural_t messageType, void *arg ) { if( messageType == kIOMessageServiceIsTerminated ) { InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; LockMut( This->m_ChangeLock ); This->m_bChanged = true; } }
void ArchHooks::SetHasFocus( bool bHasFocus ) { if( bHasFocus == m_bHasFocus ) return; m_bHasFocus = bHasFocus; LOG->Trace( "App %s focus", bHasFocus? "has":"doesn't have" ); LockMut( g_Mutex ); m_bFocusChanged = true; }
void RageSoundDriver_ALSA9::MixerThread() { while(!shutdown) { /* Sleep for the size of one chunk. */ //const int chunksize_frames = max_writeahead / num_chunks; //float sleep_secs = (float(chunksize_frames) / samplerate); usleep( 20000 ); // int(1000 * sleep_secs)); LockMut( m_Mutex ); for( unsigned i = 0; i < stream_pool.size(); ++i ) { /* We're only interested in PLAYING and FLUSHING sounds. */ if( stream_pool[i]->state != stream::PLAYING && stream_pool[i]->state != stream::FLUSHING ) continue; /* inactive */ if( stream_pool[i]->bPaused ) continue; /* paused */ bool bEOF = false; while( !shutdown && stream_pool[i]->GetData(bEOF) && !bEOF ) ; if( bEOF ) { /* FLUSHING tells the mixer thread to release the stream once str->flush_bufs * buffers have been flushed. */ stream_pool[i]->state = stream::FLUSHING; /* Flush two buffers worth of data. */ stream_pool[i]->flush_pos = stream_pool[i]->pcm->GetPlayPos(); LOG->Trace("eof, fl to %i", (int)stream_pool[i]->flush_pos); } } for(unsigned i = 0; i < stream_pool.size(); ++i) { if( stream_pool[i]->state != stream_pool[i]->FLUSHING ) continue; int ps = stream_pool[i]->pcm->GetPosition(); if( ps < stream_pool[i]->flush_pos ) continue; /* stopping but still flushing */ /* The sound has stopped and flushed all of its buffers. */ stream_pool[i]->bPaused = false; stream_pool[i]->pcm->Stop(); stream_pool[i]->state = stream::FINISHED; } } }
RageSound *RageSoundManager::GetSoundByID( int ID ) { LockMut( g_SoundManMutex ); /* Find the sound with p.ID. */ map<int,RageSound *>::iterator it; it = all_sounds.find( ID ); if( it == all_sounds.end() ) return NULL; return it->second; }
void MessageManager::Subscribe( IMessageSubscriber* pSubscriber, const RString& sMessage ) { LockMut(g_Mutex); SubscribersSet& subs = g_MessageToSubscribers[sMessage]; #ifdef DEBUG SubscribersSet::iterator iter = subs.find(pSubscriber); ASSERT_M( iter == subs.end(), ssprintf("already subscribed to '%s'",sMessage.c_str()) ); #endif subs.insert( pSubscriber ); }