Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
285
Src/Winamp/ServiceManager.cpp
Normal file
285
Src/Winamp/ServiceManager.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
/** (c) Nullsoft, Inc. C O N F I D E N T I A L
|
||||
** Filename:
|
||||
** Project:
|
||||
** Description:
|
||||
** Author: Ben Allison benski@nullsoft.com
|
||||
** Created:
|
||||
**/
|
||||
#include "main.h"
|
||||
#include "ServiceManager.h"
|
||||
#include <api.h>
|
||||
#include <api/service/waservicefactory.h>
|
||||
#include "../nu/AutoLock.h"
|
||||
#include <api/syscb/callbacks/syscb.h>
|
||||
#include <api/syscb/callbacks/svccb.h>
|
||||
|
||||
using namespace Nullsoft::Utility;
|
||||
|
||||
|
||||
struct Counter
|
||||
{
|
||||
Counter( waServiceFactory *_owner, void *_ptr ) : ptr( _ptr ), owner( _owner ) {}
|
||||
|
||||
void *ptr;
|
||||
waServiceFactory *owner;
|
||||
};
|
||||
|
||||
ServiceManager::ServiceManager() : serviceGuard(512)
|
||||
{}
|
||||
|
||||
int ServiceManager::service_register( waServiceFactory *svc )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_register" ) );
|
||||
FOURCC service_type = svc->getServiceType();
|
||||
|
||||
// add the service to the master list
|
||||
services.push_back( svc );
|
||||
|
||||
// add it to the by-type lookup
|
||||
ServiceList *&type_list = services_by_type[ service_type ];
|
||||
if ( !type_list )
|
||||
type_list = new ServiceList;
|
||||
|
||||
type_list->push_back( svc );
|
||||
|
||||
// send notifications
|
||||
svc->serviceNotify( SvcNotify::ONREGISTERED );
|
||||
WASABI_API_SYSCB->syscb_issueCallback( SysCallback::SERVICE, SvcCallback::ONREGISTER, (intptr_t)service_type, reinterpret_cast<intptr_t>( svc ) );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ServiceManager::service_deregister( waServiceFactory *svc )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_deregister" ) );
|
||||
FOURCC service_type = svc->getServiceType();
|
||||
|
||||
// remove it from the master list
|
||||
//services.eraseObject(svc);
|
||||
auto it = std::find( services.begin(), services.end(), svc );
|
||||
if ( it != services.end() )
|
||||
services.erase( it );
|
||||
|
||||
// and from the type lookup map
|
||||
ServiceList *type_list = services_by_type[ service_type ];
|
||||
if ( type_list )
|
||||
{
|
||||
//type_list->eraseObject(svc);
|
||||
auto it = std::find( type_list->begin(), type_list->end(), svc );
|
||||
if ( it != type_list->end() )
|
||||
type_list->erase( it );
|
||||
}
|
||||
|
||||
WASABI_API_SYSCB->syscb_issueCallback( SysCallback::SERVICE, SvcCallback::ONDEREGISTER, (intptr_t)service_type, reinterpret_cast<intptr_t>( svc ) );
|
||||
svc->serviceNotify( SvcNotify::ONDEREGISTERED );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t ServiceManager::service_getNumServices( FOURCC svc_type )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_getNumServices" ) );
|
||||
if ( svc_type )
|
||||
{
|
||||
ServiceList *type_list = services_by_type[ svc_type ];
|
||||
if ( type_list )
|
||||
return type_list->size();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return services.size();
|
||||
}
|
||||
|
||||
waServiceFactory *ServiceManager::service_enumService( FOURCC svc_type, size_t n )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_enumService" ) );
|
||||
ServiceList *type_list = 0;
|
||||
if ( svc_type )
|
||||
type_list = services_by_type[ svc_type ];
|
||||
else
|
||||
type_list = &services;
|
||||
|
||||
if ( type_list && n < type_list->size() )
|
||||
return type_list->at( n );
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
waServiceFactory *ServiceManager::service_getServiceByGuid( GUID guid )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_getServiceByGuid" ) );
|
||||
for ( waServiceFactory *l_service : services )
|
||||
{
|
||||
if ( l_service->getGuid() == guid )
|
||||
return l_service;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ServiceManager::service_lock( waServiceFactory *owner, void *svcptr )
|
||||
{
|
||||
if ( owner == NULL || svcptr == NULL )
|
||||
return 0;
|
||||
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_lock" ) );
|
||||
locks.push_back( new Counter( owner, svcptr ) );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ServiceManager::service_clientLock( void *svcptr )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ServiceManager::service_release( void *svcptr )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_release" ) );
|
||||
for ( size_t i = 0; i != locks.size(); i++ )
|
||||
{
|
||||
if ( locks[ i ]->ptr == svcptr )
|
||||
{
|
||||
void *ptr = locks[ i ]->ptr;
|
||||
waServiceFactory *owner = locks[ i ]->owner;
|
||||
|
||||
delete locks[ i ];
|
||||
|
||||
locks.erase( locks.begin() + i );
|
||||
owner->releaseInterface( ptr );
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ServiceManager::service_getTypeName( FOURCC svc_type )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ServiceManager::service_unlock( void *svcptr )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_unlock" ) );
|
||||
for ( size_t i = 0; i != locks.size(); i++ )
|
||||
{
|
||||
if ( locks[ i ]->ptr == svcptr )
|
||||
{
|
||||
delete locks[ i ];
|
||||
locks.erase( locks.begin() + i );
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ServiceManager::service_isvalid( FOURCC svctype, waServiceFactory *service )
|
||||
{
|
||||
AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_isvalid" ) );
|
||||
//return !!services.contains(service);
|
||||
return ( services.end() != std::find( services.begin(), services.end(), service ) );
|
||||
}
|
||||
|
||||
int ServiceManager::service_compactDuplicates( waServiceFactory *me )
|
||||
{
|
||||
// first, find 'me'
|
||||
GUID guid = me->getGuid();
|
||||
|
||||
size_t me_index = 0;
|
||||
|
||||
//bool found = services.findItem(me, &me_index);
|
||||
//if (!found)
|
||||
// return 1;
|
||||
if ( services.end() == std::find( services.begin(), services.end(), me ) )
|
||||
return 1;
|
||||
|
||||
ServiceList *type_list = services_by_type[ me->getServiceType() ];
|
||||
|
||||
// go in reverse order because service to compact is likely at the end
|
||||
size_t n = services.size();
|
||||
while ( n-- ) // n is guaranteed to be >0 because otherwise the 'find' loop above would have failed
|
||||
{
|
||||
waServiceFactory *n_service = services[ n ];
|
||||
if ( n != me_index && n_service != me && n_service->getGuid() == guid )
|
||||
{
|
||||
services[ me_index ] = n_service;
|
||||
services.erase( services.begin() + n );
|
||||
|
||||
// fix up our by-type cache
|
||||
if ( type_list )
|
||||
{
|
||||
size_t me_index = 0;
|
||||
size_t n_index = 0;
|
||||
|
||||
//----------------------------------------------------
|
||||
// Replaced with code below this commented code
|
||||
//if (type_list->findItem_reverse(n_service, &n_index) && type_list->findItem(me, &me_index))
|
||||
//{
|
||||
// type_list->at(me_index) = n_service;
|
||||
// type_list->eraseindex(n_index);
|
||||
//}
|
||||
|
||||
bool foundService = false;
|
||||
for ( int idx = type_list->size() - 1; idx >= 0; idx-- )
|
||||
{
|
||||
if ( type_list->at( idx ) == n_service )
|
||||
{
|
||||
foundService = true;
|
||||
n_index = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool foundMe = false;
|
||||
for ( int idx2 = 0; idx2 < type_list->size(); idx2++ )
|
||||
{
|
||||
if ( type_list->at( idx2 ) == me )
|
||||
{
|
||||
foundMe = true;
|
||||
me_index = idx2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( foundService && foundMe )
|
||||
{
|
||||
type_list->at( me_index ) = n_service;
|
||||
type_list->erase( type_list->begin() + n_index );
|
||||
}
|
||||
//--------------------------------------------------
|
||||
}
|
||||
|
||||
me->serviceNotify( SvcNotify::ONDEREGISTERED );
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CBCLASS
|
||||
#undef CBCLASS
|
||||
#endif
|
||||
|
||||
#define CBCLASS ServiceManager
|
||||
START_DISPATCH;
|
||||
CB( API_SERVICE_SERVICE_REGISTER, service_register );
|
||||
CB( API_SERVICE_SERVICE_DEREGISTER, service_deregister );
|
||||
CB( API_SERVICE_SERVICE_GETNUMSERVICES, service_getNumServices );
|
||||
CB( API_SERVICE_SERVICE_ENUMSERVICE, service_enumService );
|
||||
CB( API_SERVICE_SERVICE_GETSERVICEBYGUID, service_getServiceByGuid );
|
||||
CB( API_SERVICE_SERVICE_LOCK, service_lock );
|
||||
CB( API_SERVICE_SERVICE_CLIENTLOCK, service_clientLock );
|
||||
CB( API_SERVICE_SERVICE_RELEASE, service_release );
|
||||
CB( API_SERVICE_SERVICE_GETTYPENAME, service_getTypeName );
|
||||
CB( API_SERVICE_SERVICE_UNLOCK, service_unlock );
|
||||
CB( API_SERVICE_ISVALID, service_isvalid );
|
||||
CB( API_SERVICE_COMPACT_DUPLICATES, service_compactDuplicates );
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
Loading…
Add table
Add a link
Reference in a new issue