123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- #include "JSAPI2_CallbackManager.h"
- #include "JSAPI2_TransportAPI.h"
- #include "JSAPI2_AsyncDownloader.h"
- #include "JSAPI2_MediaCore.h"
- #include "api.h"
- JSAPI2::CallbackManager JSAPI2::callbackManager;
- JSAPI2::CallbackManager::CallbackManager() : callbackGuard("JSAPI2::CallbackManager::callbackGuard")
- {}
- void JSAPI2::CallbackManager::Register( JSAPI2::TransportAPI *me )
- {
- /* benski> important note:
- even thought JSAPI2::Transport inherits from IUnknown,
- we don't call AddRef here!
- because this would introduce a circular reference.
- JSAPI2::TransportAPI will call Deregister during it's
- destructor.
- */
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- transports.push_back( new TransportCallback( me ) );
- }
- void JSAPI2::CallbackManager::Deregister( JSAPI2::TransportAPI *me )
- {
- /* benski> important note:
- even thought JSAPI2::Transport inherits from IUnknown,
- we don't call Release here!
- because this would introduce a circular reference.
- JSAPI2::TransportAPI will call Deregister during it's
- destructor.
- */
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( size_t i = 0; i != transports.size(); i++ )
- {
- TransportCallback *callback = transports[ i ];
- if ( callback->api == me )
- {
- delete callback;
- transports.erase( transports.begin() + i );
- i--;
- }
- }
- }
- void JSAPI2::CallbackManager::Register( JSAPI2::MediaCoreAPI *me )
- {
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- //if (!mediaCores.contains(me))
- if ( mediaCores.end() == std::find( mediaCores.begin(), mediaCores.end(), me ) )
- {
- mediaCores.push_back( me );
- }
- }
- void JSAPI2::CallbackManager::Deregister( JSAPI2::MediaCoreAPI *me )
- {
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- auto it = mediaCores.begin();
- while ( it != mediaCores.end() )
- {
- if ( *it != me )
- {
- it++;
- continue;
- }
- it = mediaCores.erase( it );
- }
- }
- void JSAPI2::CallbackManager::Register( JSAPI2::AsyncDownloaderAPI *me )
- {
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- asyncDownloaders.push_back( new AsyncDownloaderCallback( me ) );
- }
- void JSAPI2::CallbackManager::Deregister( JSAPI2::AsyncDownloaderAPI *me )
- {
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( size_t i = 0; i != asyncDownloaders.size(); i++ )
- {
- AsyncDownloaderCallback *callback = asyncDownloaders[ i ];
- if ( callback->api == me )
- {
- delete callback;
- asyncDownloaders.erase( asyncDownloaders.begin() + i );
- i--;
- }
- }
- }
- /* --- OnStop --- */
- struct OnStopAPCData
- {
- JSAPI2::TransportAPI *transport;
- int position;
- int is_full_stop;
- };
- static void CALLBACK CMGR_OnStopAPC(ULONG_PTR param)
- {
- OnStopAPCData *data = (OnStopAPCData *)param;
- data->transport->OnStop(data->position, data->is_full_stop);
- data->transport->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnStop(int position, int is_full_stop)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock(callbackGuard);
- for ( TransportCallback *l_transport : transports )
- {
- OnStopAPCData *data = new OnStopAPCData;
- data->transport = l_transport->api;
- data->position = position;
- data->is_full_stop = is_full_stop;
- data->transport->AddRef(); // so it doesn't disappear while we're switching threads
- if ( threadId == l_transport->threadId )
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnStopAPC( (ULONG_PTR)data );
- }
- else
- {
- // different thread, do an APC
- if ( QueueUserAPC( CMGR_OnStopAPC, l_transport->threadHandle, (ULONG_PTR)data ) == 0 )
- {
- data->transport->Release();
- delete data;
- }
- }
- }
- }
- /* --- --- */
- /* --- OnPlay --- */
- struct OnPlayAPC
- {
- JSAPI2::TransportAPI *transport;
- wchar_t *filename;
- };
- static void CALLBACK CMGR_OnPlayAPC(ULONG_PTR param)
- {
- OnPlayAPC *data = (OnPlayAPC *)param;
- data->transport->OnPlay(data->filename);
- free(data->filename);
- data->transport->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnPlay(const wchar_t *filename)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock(callbackGuard);
- for ( TransportCallback *l_transport : transports )
- {
- OnPlayAPC *data = new OnPlayAPC;
- data->transport = l_transport->api;
- data->filename = _wcsdup(filename);
- data->transport->AddRef(); // so it doesn't disappear while we're switching threads
- if ( threadId == l_transport->threadId )
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnPlayAPC( (ULONG_PTR)data );
- }
- else
- {
- // different thread, do an APC
- if ( QueueUserAPC( CMGR_OnPlayAPC, l_transport->threadHandle, (ULONG_PTR)data ) == 0 )
- {
- data->transport->Release();
- free( data->filename );
- delete data;
- }
- }
- }
- }
- /* --- --- */
- struct OnPauseAPC
- {
- JSAPI2::TransportAPI *transport;
- bool pause_state;
- };
- static void CALLBACK CMGR_OnPauseAPC(ULONG_PTR param)
- {
- OnPauseAPC *data = (OnPauseAPC *)param;
- data->transport->OnPause(data->pause_state);
- data->transport->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnPause(bool pause_state)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( TransportCallback *l_transport : transports )
- {
- OnPauseAPC *data = new OnPauseAPC;
- data->transport = l_transport->api;
- data->pause_state = pause_state;
- data->transport->AddRef(); // so it doesn't disappear while we're switching threads
- if (threadId == l_transport->threadId)
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnPauseAPC((ULONG_PTR)data);
- }
- else
- {
- // different thread, do an APC
- if (QueueUserAPC(CMGR_OnPauseAPC, l_transport->threadHandle, (ULONG_PTR)data) == 0)
- {
- data->transport->Release();
- delete data;
- }
- }
- }
- }
- /* --- --- */
- bool JSAPI2::CallbackManager::OverrideMetadata( const wchar_t *filename, const wchar_t *tag, wchar_t *out, size_t outCch )
- {
- if ( NULL != filename && NULL != tag && NULL != out )
- {
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( MediaCoreAPI *l_mediaCore : mediaCores )
- {
- if ( l_mediaCore->OverrideMetadata( filename, tag, out, outCch ) )
- return true;
- }
- }
- return false;
- }
- /* --- OnInit --- */
- struct OnInitAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- };
- static void CALLBACK CMGR_OnInitAPC(ULONG_PTR param)
- {
- OnInitAPC *data = (OnInitAPC *)param;
- data->asyncDownloader->OnInit(data->url);
- free(data->url);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnInit( const wchar_t *url, const wchar_t *onlinesvcId )
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( AsyncDownloaderCallback *l_downloader : asyncDownloaders )
- {
- if ( wcscmp( onlinesvcId, l_downloader->api->GetKey() ) )
- continue; //only call back to the same online service that issued the download reqeust
- OnInitAPC *data = new OnInitAPC;
- data->asyncDownloader = l_downloader->api;
- data->url = _wcsdup( url );
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if ( threadId == l_downloader->threadId )
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnInitAPC( (ULONG_PTR)data );
- }
- else
- {
- // different thread, do an APC
- if ( QueueUserAPC( CMGR_OnInitAPC, l_downloader->threadHandle, (ULONG_PTR)data ) == 0 )
- {
- data->asyncDownloader->Release();
- free( data->url );
- delete data;
- }
- }
- }
- }
- /* --- OnConnect --- */
- struct OnConnectAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- };
- static void CALLBACK CMGR_OnConnectAPC(ULONG_PTR param)
- {
- OnConnectAPC *data = (OnConnectAPC *)param;
- data->asyncDownloader->OnConnect(data->url);
- free(data->url);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnConnect( const wchar_t *url, const wchar_t *onlinesvcId )
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( AsyncDownloaderCallback *l_downloader : asyncDownloaders )
- {
- if ( wcscmp( onlinesvcId, l_downloader->api->GetKey() ) )
- continue; //only call back to the same online service that issued the download reqeust
- OnConnectAPC *data = new OnConnectAPC;
- data->asyncDownloader = l_downloader->api;
- data->url = _wcsdup( url );
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if ( threadId == l_downloader->threadId )
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnConnectAPC( (ULONG_PTR)data );
- }
- else
- {
- // different thread, do an APC
- if ( QueueUserAPC( CMGR_OnConnectAPC, l_downloader->threadHandle, (ULONG_PTR)data ) == 0 )
- {
- data->asyncDownloader->Release();
- free( data->url );
- delete data;
- }
- }
- }
- }
- /* --- OnCancel --- */
- struct OnCancelAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- };
- static void CALLBACK CMGR_OnCancelAPC(ULONG_PTR param)
- {
- OnCancelAPC *data = (OnCancelAPC *)param;
- data->asyncDownloader->OnCancel(data->url);
- free(data->url);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnCancel( const wchar_t *url, const wchar_t *onlinesvcId )
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock( callbackGuard );
- for ( AsyncDownloaderCallback *l_downloader : asyncDownloaders )
- {
- if ( wcscmp( onlinesvcId, l_downloader->api->GetKey() ) )
- continue; //only call back to the same online service that issued the download reqeust
- OnCancelAPC *data = new OnCancelAPC;
- data->asyncDownloader = l_downloader->api;
- data->url = _wcsdup( url );
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if ( threadId == l_downloader->threadId )
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnCancelAPC( (ULONG_PTR)data );
- }
- else
- {
- // different thread, do an APC
- if ( QueueUserAPC( CMGR_OnCancelAPC, l_downloader->threadHandle, (ULONG_PTR)data ) == 0 )
- {
- data->asyncDownloader->Release();
- free( data->url );
- delete data;
- }
- }
- }
- }
- /* --- OnData --- */
- struct OnDataAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- size_t downloadedlen;
- size_t totallen;
- };
- static void CALLBACK CMGR_OnDataAPC(ULONG_PTR param)
- {
- OnDataAPC *data = (OnDataAPC *)param;
- data->asyncDownloader->OnData(data->url, data->downloadedlen, data->totallen);
- free(data->url);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnData(const wchar_t *url, size_t downloadedlen, size_t totallen, const wchar_t *onlinesvcId)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock(callbackGuard);
- for ( AsyncDownloaderCallback *downloader : asyncDownloaders )
- {
- if ( wcscmp(onlinesvcId, downloader->api->GetKey()) )
- continue; //only call back to the same online service that issued the download reqeust
- OnDataAPC *data = new OnDataAPC;
- data->asyncDownloader = downloader->api;
- data->url = _wcsdup(url);
- data->downloadedlen = downloadedlen;
- data->totallen = totallen;
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if (threadId == downloader->threadId)
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnDataAPC((ULONG_PTR)data);
- }
- else
- {
- // different thread, do an APC
- if (QueueUserAPC(CMGR_OnDataAPC, downloader->threadHandle, (ULONG_PTR)data) == 0)
- {
- data->asyncDownloader->Release();
- free(data->url);
- delete data;
- }
- }
- }
- }
- /* --- OnError --- */
- struct OnErrorAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- int error;
- };
- static void CALLBACK CMGR_OnErrorAPC(ULONG_PTR param)
- {
- OnErrorAPC *data = (OnErrorAPC *)param;
- data->asyncDownloader->OnError(data->url, data->error);
- free(data->url);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnError(const wchar_t *url, int error, const wchar_t *onlinesvcId)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock(callbackGuard);
- for ( AsyncDownloaderCallback *downloader : asyncDownloaders )
- {
- if ( wcscmp(onlinesvcId, downloader->api->GetKey()) )
- continue; //only call back to the same online service that issued the download reqeust
- OnErrorAPC *data = new OnErrorAPC;
- data->asyncDownloader = downloader->api;
- data->url = _wcsdup(url);
- data->error = error;
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if (threadId == downloader->threadId)
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnErrorAPC((ULONG_PTR)data);
- }
- else
- {
- // different thread, do an APC
- if (QueueUserAPC(CMGR_OnErrorAPC, downloader->threadHandle, (ULONG_PTR)data) == 0)
- {
- data->asyncDownloader->Release();
- free(data->url);
- delete data;
- }
- }
- }
- }
- /* --- OnFinish --- */
- struct OnFinishAPC
- {
- JSAPI2::AsyncDownloaderAPI *asyncDownloader;
- wchar_t *url;
- wchar_t *destfilename;
- };
- static void CALLBACK CMGR_OnFinishAPC(ULONG_PTR param)
- {
- OnFinishAPC *data = (OnFinishAPC *)param;
- data->asyncDownloader->OnFinish(data->url, data->destfilename);
- free(data->url);
- free(data->destfilename);
- data->asyncDownloader->Release();
- delete data;
- }
- void JSAPI2::CallbackManager::OnFinish(const wchar_t *url, const wchar_t *destfilename, const wchar_t *onlinesvcId)
- {
- DWORD threadId = GetCurrentThreadId();
- Nullsoft::Utility::AutoLock lock(callbackGuard);
- for ( AsyncDownloaderCallback *downloader : asyncDownloaders )
- {
- if ( wcscmp(onlinesvcId, downloader->api->GetKey()) )
- continue; //only call back to the same online service that issued the download reqeust
- OnFinishAPC *data = new OnFinishAPC;
- data->asyncDownloader = downloader->api;
- data->url = _wcsdup(url);
- data->destfilename = _wcsdup(destfilename);
- data->asyncDownloader->AddRef(); // so it doesn't disappear while we're switching threads
- if (threadId == downloader->threadId)
- {
- // same thread! huzzah but I wonder how that happened :)
- CMGR_OnFinishAPC((ULONG_PTR)data);
- }
- else
- {
- // different thread, do an APC
- if (QueueUserAPC(CMGR_OnFinishAPC, downloader->threadHandle, (ULONG_PTR)data) == 0)
- {
- data->asyncDownloader->Release();
- free(data->url);
- free(data->destfilename);
- delete data;
- }
- }
- }
- }
|