Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
630
Src/playlist/PlaylistManager.cpp
Normal file
630
Src/playlist/PlaylistManager.cpp
Normal file
|
@ -0,0 +1,630 @@
|
|||
#include <strsafe.h>
|
||||
#include <shlwapi.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#include "main.h"
|
||||
#include "resource.h"
|
||||
#include "PlaylistManager.h"
|
||||
#include "ifc_playlistloader.h"
|
||||
#include "M3ULoader.h"
|
||||
#include "M3UWriter.h"
|
||||
#include "PLSWriter.h"
|
||||
#include "M3U8Writer.h"
|
||||
#include "B4SWriter.h"
|
||||
#include "../nu/AutoChar.h"
|
||||
#include "Playlist.h"
|
||||
#include "../playlist/svc_playlisthandler.h"
|
||||
#include "../playlist/Handler.h"
|
||||
#include "../nu/AutoWide.h"
|
||||
#include "Playlist.h"
|
||||
#include "api/service/services.h"
|
||||
#include "api__playlist.h"
|
||||
#include "api/service/waservicefactory.h"
|
||||
#include "PlaylistCounter.h"
|
||||
#include "ifc_playlistloadercallback.h"
|
||||
#include "ifc_playlistdirectorycallback.h"
|
||||
|
||||
#include "..\WAT\WAT.h"
|
||||
|
||||
class NoRecurseCallback : public ifc_playlistdirectorycallback
|
||||
{
|
||||
public:
|
||||
NoRecurseCallback( ifc_playlistdirectorycallback *_callback ) : callback( _callback ) {}
|
||||
bool ShouldRecurse( const wchar_t *path ) { return false; }
|
||||
bool ShouldLoad( const wchar_t *filename ) { return callback->ShouldLoad( filename ); }
|
||||
|
||||
ifc_playlistdirectorycallback *callback;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#define CBCLASS NoRecurseCallback
|
||||
START_DISPATCH;
|
||||
CB( IFC_PLAYLISTDIRECTORYCALLBACK_SHOULDRECURSE, ShouldRecurse )
|
||||
CB( IFC_PLAYLISTDIRECTORYCALLBACK_SHOULDLOAD, ShouldLoad )
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
||||
|
||||
|
||||
static void MakeRelativePathName( const wchar_t *filename, wchar_t *outFile, size_t cch, const wchar_t *path )
|
||||
{
|
||||
wchar_t outPath[ MAX_PATH ] = { 0 };
|
||||
|
||||
int common = PathCommonPrefixW( path, filename, outPath );
|
||||
if ( common && common == wcslen( path ) )
|
||||
{
|
||||
PathAddBackslashW( outPath );
|
||||
const wchar_t *p = filename + wcslen( outPath );
|
||||
lstrcpynW( outFile, p, (int)cch );
|
||||
}
|
||||
else if ( !PathIsUNCW( filename ) && PathIsSameRootW( filename, path ) )
|
||||
{
|
||||
if ( outFile[ 1 ] == ':' )
|
||||
lstrcpynW( outFile, filename + 2, (int)cch );
|
||||
}
|
||||
}
|
||||
|
||||
static void PlayList_makerelative( const wchar_t *base, wchar_t *filename, size_t cch )
|
||||
{
|
||||
MakeRelativePathName( filename, filename, cch, base );
|
||||
}
|
||||
|
||||
|
||||
PlaylistManager playlistManager;
|
||||
|
||||
struct LoaderPair
|
||||
{
|
||||
ifc_playlistloader *loader;
|
||||
svc_playlisthandler *handler;
|
||||
};
|
||||
|
||||
static LoaderPair CreateLoader( const wchar_t *filename )
|
||||
{
|
||||
LoaderPair ret = { 0, 0 };
|
||||
int n = 0;
|
||||
waServiceFactory *sf = 0;
|
||||
|
||||
while ( sf = WASABI_API_SVC->service_enumService( WaSvc::PLAYLISTHANDLER, n++ ) )
|
||||
{
|
||||
svc_playlisthandler *handler = static_cast<svc_playlisthandler *>( sf->getInterface() );
|
||||
if ( handler )
|
||||
{
|
||||
if ( handler->SupportedFilename( filename ) == SVC_PLAYLISTHANDLER_SUCCESS )
|
||||
{
|
||||
ret.loader = handler->CreateLoader( filename );
|
||||
ret.handler = handler;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sf->releaseInterface( handler );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: sniff file if no one claims it
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DestroyLoader( LoaderPair &loader )
|
||||
{
|
||||
loader.handler->ReleaseLoader( loader.loader );
|
||||
}
|
||||
|
||||
// a simple loader...
|
||||
int PlaylistManager::Load( const wchar_t *filename, ifc_playlistloadercallback *playlist )
|
||||
{
|
||||
LoaderPair loaderPair = CreateLoader( filename );
|
||||
ifc_playlistloader *loader = loaderPair.loader;
|
||||
|
||||
if ( !loader )
|
||||
return PLAYLISTMANAGER_LOAD_NO_LOADER; // failed to find a loader
|
||||
|
||||
// TODO: make our own ifc_playlistloadercallback, so we can handle nested playlists
|
||||
int res = loader->Load( filename, playlist );
|
||||
DestroyLoader( loaderPair );
|
||||
|
||||
if ( res != IFC_PLAYLISTLOADER_SUCCESS ) // TODO: switch on the error code and return a more specific error
|
||||
return PLAYLISTMANAGER_LOAD_LOADER_OPEN_FAILED;
|
||||
|
||||
return PLAYLISTMANAGER_SUCCESS;
|
||||
}
|
||||
|
||||
int PlaylistManager::LoadAs( const wchar_t *filename, const wchar_t *ext, ifc_playlistloadercallback *playlist )
|
||||
{
|
||||
LoaderPair loaderPair = CreateLoader( ext );
|
||||
ifc_playlistloader *loader = loaderPair.loader;
|
||||
|
||||
if ( !loader )
|
||||
return PLAYLISTMANAGER_LOAD_NO_LOADER; // failed to find a loader
|
||||
|
||||
// TODO: make our own ifc_playlistloadercallback, so we can handle nested playlists
|
||||
int res = loader->Load( filename, playlist );
|
||||
DestroyLoader( loaderPair );
|
||||
|
||||
if ( res != IFC_PLAYLISTLOADER_SUCCESS ) // TODO: switch on the error code and return a more specific error
|
||||
return PLAYLISTMANAGER_LOAD_LOADER_OPEN_FAILED;
|
||||
|
||||
return PLAYLISTMANAGER_SUCCESS;
|
||||
}
|
||||
|
||||
int PlaylistManager::LoadFromDialog( const wchar_t *fns, ifc_playlistloadercallback *playlist )
|
||||
{
|
||||
wchar_t buf[ MAX_PATH ] = { 0 };
|
||||
const wchar_t *path = fns;
|
||||
fns += wcslen( fns ) + 1;
|
||||
|
||||
while ( fns && *fns )
|
||||
{
|
||||
if ( *path )
|
||||
PathCombineW( buf, path, fns );
|
||||
else
|
||||
StringCchCopyW( buf, MAX_PATH, fns );
|
||||
|
||||
if ( Load( buf, playlist ) != PLAYLISTMANAGER_SUCCESS )
|
||||
{
|
||||
if ( playlist->OnFile( buf, 0, -1, 0 ) != ifc_playlistloadercallback::LOAD_CONTINUE )
|
||||
return PLAYLIST_SUCCESS;
|
||||
}
|
||||
|
||||
fns += wcslen( fns ) + 1;
|
||||
}
|
||||
return PLAYLIST_SUCCESS;
|
||||
}
|
||||
|
||||
int PlaylistManager::LoadFromANSIDialog( const char *fns, ifc_playlistloadercallback *playlist )
|
||||
{
|
||||
char buf[ MAX_PATH ] = { 0 };
|
||||
const char *path = fns;
|
||||
fns += lstrlenA( fns ) + 1;
|
||||
|
||||
while ( fns && *fns )
|
||||
{
|
||||
if ( *path )
|
||||
PathCombineA( buf, path, fns );
|
||||
else
|
||||
lstrcpynA( buf, fns, MAX_PATH );
|
||||
|
||||
AutoWide wideFn( buf );
|
||||
if ( Load( wideFn, playlist ) != PLAYLISTMANAGER_SUCCESS )
|
||||
{
|
||||
if ( playlist->OnFile( wideFn, 0, -1, 0 ) != ifc_playlistloadercallback::LOAD_CONTINUE )
|
||||
return PLAYLIST_SUCCESS;
|
||||
}
|
||||
|
||||
fns += lstrlenA( fns ) + 1;
|
||||
}
|
||||
return PLAYLIST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int PlaylistManager::Save( const wchar_t *filename, ifc_playlist *playlist )
|
||||
{
|
||||
const wchar_t *ext = PathFindExtensionW( filename );
|
||||
PlaylistWriter *writer = 0;
|
||||
|
||||
if ( !lstrcmpiW( ext, L".M3U" ) )
|
||||
writer = new M3UWriter;
|
||||
else if ( !lstrcmpiW( ext, L".M3U8" ) )
|
||||
writer = new M3U8Writer;
|
||||
else if ( !lstrcmpiW( ext, L".PLS" ) )
|
||||
writer = new PLSWriter;
|
||||
else if ( !lstrcmpiW( ext, L".B4S" ) )
|
||||
writer = new B4SWriter;
|
||||
else
|
||||
return PLAYLISTMANAGER_FAILED;
|
||||
|
||||
wchar_t base[ MAX_PATH ] = { 0 };
|
||||
StringCchCopyW( base, MAX_PATH, filename );
|
||||
PathRemoveFileSpecW( base );
|
||||
PathRemoveBackslashW( base );
|
||||
|
||||
if ( !writer->Open( filename ) )
|
||||
{
|
||||
delete writer;
|
||||
|
||||
return PLAYLISTMANAGER_FAILED;
|
||||
}
|
||||
|
||||
size_t numItems = playlist->GetNumItems();
|
||||
wchar_t itemname[ FILENAME_SIZE ] = { 0 };
|
||||
wchar_t title[ FILETITLE_SIZE ] = { 0 };
|
||||
wchar_t cloud_info[ 512 ] = { 0 };
|
||||
int length = 0;
|
||||
|
||||
wchar_t l_tvg_id[ 10 ] = { 0 };
|
||||
wchar_t l_tvg_name[ FILETITLE_SIZE ] = { 0 };
|
||||
wchar_t l_tvg_logo[ 512 ] = { 0 };
|
||||
wchar_t l_group_title[ 64 ] = { 0 };
|
||||
|
||||
wchar_t l_ext[ 10 ] = { 0 };
|
||||
|
||||
wa::strings::wa_string l_extented_infos_line( "" );
|
||||
|
||||
for ( size_t i = 0; i != numItems; i++ )
|
||||
{
|
||||
if ( playlist->GetItem( i, itemname, FILENAME_SIZE ) )
|
||||
{
|
||||
//PlayList_makerelative( base, itemname, FILENAME_SIZE );
|
||||
|
||||
// this is used to preserve 'cloud' specific data in playlists
|
||||
// and should only get a response from a cloud-based ml_playlist
|
||||
if ( playlist->GetItemExtendedInfo( i, L"cloud", cloud_info, 512 ) )
|
||||
{
|
||||
writer->Write( cloud_info );
|
||||
}
|
||||
|
||||
|
||||
l_extented_infos_line.clear();
|
||||
|
||||
if ( playlist->GetItemExtendedInfo( i, L"tvg-name", l_tvg_name, FILETITLE_SIZE ) )
|
||||
{
|
||||
playlist->GetItemExtendedInfo( i, L"tvg-id", l_tvg_id, 10 );
|
||||
playlist->GetItemExtendedInfo( i, L"tvg-logo", l_tvg_logo, 512 );
|
||||
playlist->GetItemExtendedInfo( i, L"group-title", l_group_title, 64 );
|
||||
|
||||
l_extented_infos_line = L"tvg-id";
|
||||
l_extented_infos_line.append( L"=\"" );
|
||||
l_extented_infos_line.append( l_tvg_id );
|
||||
l_extented_infos_line.append( L"\" " );
|
||||
|
||||
l_extented_infos_line.append( L"tvg-name" );
|
||||
l_extented_infos_line.append( L"=\"" );
|
||||
l_extented_infos_line.append( l_tvg_name );
|
||||
l_extented_infos_line.append( L"\" " );
|
||||
|
||||
l_extented_infos_line.append( L"tvg-logo" );
|
||||
l_extented_infos_line.append( L"=\"" );
|
||||
l_extented_infos_line.append( l_tvg_logo );
|
||||
l_extented_infos_line.append( L"\" " );
|
||||
|
||||
l_extented_infos_line.append( L"group-title" );
|
||||
l_extented_infos_line.append( L"=\"" );
|
||||
l_extented_infos_line.append( l_group_title );
|
||||
l_extented_infos_line.append( L"\" " );
|
||||
}
|
||||
|
||||
wa::strings::wa_string l_item_name( itemname );
|
||||
|
||||
if ( l_item_name.contains( "://" ) && playlist->GetItemExtendedInfo(i, L"ext", l_ext, 10) )
|
||||
{
|
||||
l_extented_infos_line = L"ext";
|
||||
l_extented_infos_line.append( L"=\"" );
|
||||
l_extented_infos_line.append( l_ext );
|
||||
l_extented_infos_line.append( L"\"" );
|
||||
}
|
||||
|
||||
if ( playlist->GetItemTitle( i, title, FILETITLE_SIZE ) )
|
||||
{
|
||||
length = playlist->GetItemLengthMilliseconds( i );
|
||||
|
||||
if ( l_extented_infos_line.empty() )
|
||||
writer->Write( itemname, title, length / 1000 );
|
||||
else
|
||||
writer->Write( itemname, title, l_extented_infos_line.GetW().c_str(), length / 1000);
|
||||
}
|
||||
else
|
||||
writer->Write( itemname );
|
||||
}
|
||||
}
|
||||
|
||||
writer->Close();
|
||||
delete writer;
|
||||
|
||||
return PLAYLISTMANAGER_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
size_t PlaylistManager::Copy( const wchar_t *destFn, const wchar_t *srcFn )
|
||||
{
|
||||
Playlist copy;
|
||||
|
||||
Load( srcFn, © );
|
||||
Save( destFn, © );
|
||||
|
||||
return copy.GetNumItems();
|
||||
}
|
||||
|
||||
|
||||
size_t PlaylistManager::CountItems( const wchar_t *filename )
|
||||
{
|
||||
LoaderPair loaderPair = CreateLoader( filename );
|
||||
ifc_playlistloader *loader = loaderPair.loader;
|
||||
|
||||
if ( !loader )
|
||||
return 0;
|
||||
|
||||
PlaylistCounter counter;
|
||||
loader->Load( filename, &counter );
|
||||
|
||||
DestroyLoader( loaderPair );
|
||||
return counter.count;
|
||||
}
|
||||
|
||||
|
||||
int PlaylistManager::GetLengthMilliseconds( const wchar_t *filename )
|
||||
{
|
||||
LoaderPair loaderPair = CreateLoader( filename );
|
||||
ifc_playlistloader *loader = loaderPair.loader;
|
||||
|
||||
if ( !loader )
|
||||
return 0;
|
||||
|
||||
PlaylistCounter counter;
|
||||
loader->Load( filename, &counter );
|
||||
DestroyLoader( loaderPair );
|
||||
return (int)counter.length;
|
||||
}
|
||||
|
||||
uint64_t PlaylistManager::GetLongLengthMilliseconds( const wchar_t *filename )
|
||||
{
|
||||
LoaderPair loaderPair = CreateLoader( filename );
|
||||
ifc_playlistloader *loader = loaderPair.loader;
|
||||
|
||||
if ( !loader )
|
||||
return 0;
|
||||
|
||||
PlaylistCounter counter;
|
||||
loader->Load( filename, &counter );
|
||||
DestroyLoader( loaderPair );
|
||||
return counter.length;
|
||||
}
|
||||
|
||||
|
||||
void PlaylistManager::Randomize( ifc_playlist *playlist )
|
||||
{
|
||||
if ( playlist->Randomize( warand ) == PLAYLIST_UNIMPLEMENTED )
|
||||
{
|
||||
// TODO: do it the hard way
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistManager::Reverse( ifc_playlist *playlist )
|
||||
{
|
||||
if ( playlist->Reverse() == PLAYLIST_UNIMPLEMENTED )
|
||||
{
|
||||
// TODO: do it the hard way
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PlaylistManager::LoadDirectory( const wchar_t *directory, ifc_playlistloadercallback *callback, ifc_playlistdirectorycallback *dirCallback )
|
||||
{
|
||||
WIN32_FIND_DATAW found = { 0 };
|
||||
wchar_t filespec[ MAX_PATH ] = { 0 };
|
||||
PathCombineW( filespec, directory, L"*.*" );
|
||||
|
||||
HANDLE i = FindFirstFileW( filespec, &found );
|
||||
if ( i != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
do
|
||||
{
|
||||
// if it's another folder, then we might want to recurse into it
|
||||
if ( ( found.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) // if it's a directory
|
||||
&& wcscmp( found.cFileName, L"." ) && wcscmp( found.cFileName, L".." ) // but not . or ..
|
||||
&& ( !dirCallback || dirCallback->ShouldRecurse( found.cFileName ) ) ) // and we're allowed to recurse
|
||||
{
|
||||
if ( PathCombineW( filespec, directory, found.cFileName ) )
|
||||
{
|
||||
LoadDirectory( filespec, callback, dirCallback );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !( found.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
||||
{
|
||||
const wchar_t *ext = PathFindExtensionW( found.cFileName );
|
||||
if ( ext[ 0 ] )
|
||||
{
|
||||
if ( !_wcsicmp( ext, L".lnk" ) )
|
||||
{
|
||||
wchar_t thisf[ MAX_PATH ] = { 0 };
|
||||
wchar_t temp2[ MAX_PATH ] = { 0 };
|
||||
PathCombineW( temp2, directory, found.cFileName );
|
||||
if ( ResolveShortCut( NULL, temp2, thisf ) && GetLongPathNameW( thisf, temp2, MAX_PATH ) && lstrcmpiW( temp2, directory ) )
|
||||
{
|
||||
WIN32_FIND_DATAW d2 = { 0 };
|
||||
if ( IsUrl( temp2 ) && ( !dirCallback || dirCallback->ShouldLoad( temp2 ) ) )
|
||||
{
|
||||
if ( callback->OnFile( temp2, 0, -1, 0 ) != ifc_playlistloadercallback::LOAD_CONTINUE )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE h2 = FindFirstFileW( temp2, &d2 );
|
||||
if ( h2 != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
if ( !( d2.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
||||
{
|
||||
if ( !dirCallback || dirCallback->ShouldLoad( temp2 ) )
|
||||
{
|
||||
if ( callback->OnFile( temp2, 0, -1, 0 ) != ifc_playlistloadercallback::LOAD_CONTINUE )
|
||||
{
|
||||
FindClose( h2 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// recursively load a shortcut w/o fear of infinite recursion
|
||||
NoRecurseCallback noRecurse( dirCallback );
|
||||
LoadDirectory( temp2, callback, &noRecurse );
|
||||
}
|
||||
FindClose( h2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // !shortcut
|
||||
{
|
||||
|
||||
if ( PathCombineW( filespec, directory, found.cFileName ) &&
|
||||
( !dirCallback || dirCallback->ShouldLoad( filespec ) ) )
|
||||
{
|
||||
if ( callback->OnFile( filespec, 0, -1, 0 ) != ifc_playlistloadercallback::LOAD_CONTINUE )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( FindNextFileW( i, &found ) );
|
||||
FindClose( i );
|
||||
}
|
||||
}
|
||||
|
||||
bool PlaylistManager::CanLoad( const wchar_t *filename )
|
||||
{
|
||||
int n = 0;
|
||||
waServiceFactory *sf = 0;
|
||||
while ( sf = WASABI_API_SVC->service_enumService( WaSvc::PLAYLISTHANDLER, n++ ) )
|
||||
{
|
||||
svc_playlisthandler *handler = static_cast<svc_playlisthandler *>( sf->getInterface() );
|
||||
if ( handler )
|
||||
{
|
||||
if ( handler->SupportedFilename( filename ) == SVC_PLAYLISTHANDLER_SUCCESS )
|
||||
{
|
||||
sf->releaseInterface( handler );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sf->releaseInterface( handler );
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlaylistManager::GetExtensionList( wchar_t *extensionList, size_t extensionListCch )
|
||||
{
|
||||
extensionList[ 0 ] = 0;
|
||||
|
||||
bool first = true;
|
||||
|
||||
int n = 0, extListCch = (int)extensionListCch;
|
||||
wchar_t *extList = extensionList;
|
||||
waServiceFactory *sf = 0;
|
||||
while ( sf = WASABI_API_SVC->service_enumService( WaSvc::PLAYLISTHANDLER, n++ ) )
|
||||
{
|
||||
svc_playlisthandler *handler = static_cast<svc_playlisthandler *>( sf->getInterface() );
|
||||
if ( handler )
|
||||
{
|
||||
const wchar_t *ext = 0;
|
||||
int k = 0;
|
||||
while ( ext = handler->EnumerateExtensions( k++ ) )
|
||||
{
|
||||
if ( first )
|
||||
StringCchCatExW( extensionList, extensionListCch, L"*.", &extensionList, &extensionListCch, 0 );
|
||||
else
|
||||
StringCchCatExW( extensionList, extensionListCch, L";*.", &extensionList, &extensionListCch, 0 );
|
||||
|
||||
first = false;
|
||||
|
||||
StringCchCatExW( extensionList, extensionListCch, ext, &extensionList, &extensionListCch, 0 );
|
||||
}
|
||||
sf->releaseInterface( handler );
|
||||
}
|
||||
}
|
||||
CharUpperBuffW( extList, extListCch );
|
||||
}
|
||||
|
||||
void PlaylistManager::GetFilterList( wchar_t *extensionList, size_t extensionListCch )
|
||||
{
|
||||
extensionListCch--; // this needs to be DOUBLE null terminated, so we'll make sure there's room
|
||||
|
||||
StringCchCopyExW( extensionList, extensionListCch, WASABI_API_LNGSTRINGW( IDS_ALL_PLAYLIST_TYPES ), &extensionList, &extensionListCch, 0 );
|
||||
extensionListCch--;
|
||||
extensionList++;
|
||||
|
||||
GetExtensionList( extensionList, extensionListCch );
|
||||
|
||||
extensionListCch -= ( wcslen( extensionList ) + 1 );
|
||||
extensionList += wcslen( extensionList ) + 1;
|
||||
|
||||
int n = 0;
|
||||
waServiceFactory *sf = 0;
|
||||
while ( sf = WASABI_API_SVC->service_enumService( WaSvc::PLAYLISTHANDLER, n++ ) )
|
||||
{
|
||||
svc_playlisthandler *handler = static_cast<svc_playlisthandler *>( sf->getInterface() );
|
||||
if ( handler )
|
||||
{
|
||||
const wchar_t *name = handler->GetName();
|
||||
if ( !name )
|
||||
name = WASABI_API_LNGSTRINGW( IDS_PLAYLIST );
|
||||
|
||||
StringCchCopyExW( extensionList, extensionListCch, name, &extensionList, &extensionListCch, 0 );
|
||||
extensionList++;
|
||||
extensionListCch--;
|
||||
|
||||
bool first = true;
|
||||
const wchar_t *ext = 0;
|
||||
int k = 0;
|
||||
while ( ext = handler->EnumerateExtensions( k++ ) )
|
||||
{
|
||||
if ( first )
|
||||
StringCchCopyExW( extensionList, extensionListCch, L"*.", &extensionList, &extensionListCch, 0 );
|
||||
else
|
||||
StringCchCatExW( extensionList, extensionListCch, L";*.", &extensionList, &extensionListCch, 0 );
|
||||
|
||||
first = false;
|
||||
|
||||
StringCchCatExW( extensionList, extensionListCch, ext, &extensionList, &extensionListCch, 0 );
|
||||
}
|
||||
extensionList++;
|
||||
extensionListCch--;
|
||||
|
||||
sf->releaseInterface( handler );
|
||||
}
|
||||
}
|
||||
|
||||
extensionList[ 0 ] = 0; // ok because we reserved the room for it above
|
||||
}
|
||||
|
||||
const wchar_t *PlaylistManager::EnumExtensions( size_t num )
|
||||
{
|
||||
int n = 0;
|
||||
int total = 0;
|
||||
waServiceFactory *sf = 0;
|
||||
while ( sf = WASABI_API_SVC->service_enumService( WaSvc::PLAYLISTHANDLER, n++ ) )
|
||||
{
|
||||
svc_playlisthandler *handler = static_cast<svc_playlisthandler *>( sf->getInterface() );
|
||||
if ( handler )
|
||||
{
|
||||
const wchar_t *ext = 0;
|
||||
int k = 0;
|
||||
while ( ext = handler->EnumerateExtensions( k++ ) )
|
||||
{
|
||||
if ( total++ == num )
|
||||
return ext;
|
||||
}
|
||||
|
||||
sf->releaseInterface( handler );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define CBCLASS PlaylistManager
|
||||
START_DISPATCH;
|
||||
CB( API_PLAYLISTMANAGER_LOAD, Load )
|
||||
CB( API_PLAYLISTMANAGER_LOADAS, LoadAs )
|
||||
CB( API_PLAYLISTMANAGER_LOADNULLDELIMITED, LoadFromDialog )
|
||||
CB( API_PLAYLISTMANAGER_LOADNULLDELIMITED_ANSI, LoadFromANSIDialog )
|
||||
CB( API_PLAYLISTMANAGER_SAVE, Save )
|
||||
CB( API_PLAYLISTMANAGER_COPY, Copy )
|
||||
CB( API_PLAYLISTMANAGER_COUNT, CountItems )
|
||||
CB( API_PLAYLISTMANAGER_GETLENGTH, GetLengthMilliseconds )
|
||||
CB( API_PLAYLISTMANAGER_GETLONGLENGTH, GetLongLengthMilliseconds )
|
||||
VCB( API_PLAYLISTMANAGER_RANDOMIZE, Randomize )
|
||||
VCB( API_PLAYLISTMANAGER_REVERSE, Reverse )
|
||||
VCB( API_PLAYLISTMANAGER_LOADDIRECTORY, LoadDirectory )
|
||||
CB( API_PLAYLISTMANAGER_CANLOAD, CanLoad )
|
||||
VCB( API_PLAYLISTMANAGER_GETEXTENSIONLIST, GetExtensionList )
|
||||
VCB( API_PLAYLISTMANAGER_GETFILTERLIST, GetFilterList )
|
||||
CB( API_PLAYLISTMANAGER_ENUMEXTENSION, EnumExtensions )
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
Loading…
Add table
Add a link
Reference in a new issue