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
	}
Пример #2
0
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;
}
Пример #3
0
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 );
}
Пример #4
0
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 );
}
Пример #7
0
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");
}
Пример #9
0
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 );
}
Пример #10
0
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 );
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
	}
}
Пример #14
0
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 );
}
Пример #15
0
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;
}
Пример #16
0
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;
}
Пример #17
0
bool ArchHooks::AppFocusChanged()
{
	LockMut( g_Mutex );
	bool bFocusChanged = m_bFocusChanged;
	
	m_bFocusChanged = false;
	return bFocusChanged;
}
Пример #18
0
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 );
}
Пример #20
0
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;
}
Пример #21
0
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 );
}
Пример #22
0
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();
}
Пример #23
0
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;
}
Пример #24
0
	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;
}
Пример #26
0
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;
	}
}
Пример #27
0
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;
}
Пример #28
0
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;
		}
	}
}
Пример #29
0
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;
}
Пример #30
0
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 );
}