#include "main.h" #include "api__ml_iso.h" #include #include "../burner/obj_isocreator.h" #include "../playlist/ifc_playlistloadercallback.h" #include #include /** ** Playlist Loader callback class ** Used when this plugin loads a playlist file ** the playlist loader will call the OnFile() function ** for each playlist item */ class ISOPlaylistLoader : public ifc_playlistloadercallback { public: ISOPlaylistLoader(obj_isocreator *_creator); protected: RECVS_DISPATCH; private: void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info); obj_isocreator *creator; }; /** ** helper function ** for getting a filename location ** of where to save the ISO file **/ static bool PromptForFilename(wchar_t *filename, size_t filenameCch) { wchar_t oldCurPath[MAX_PATH], newCurPath[MAX_PATH]; OPENFILENAMEW openfilename; // null terminate the string or else we'll get a garbage filename as the 'default' filename filename[0]=0; // GetSaveFileName changes Window's working directory // which locks that folder from being deleted until Winamp closes // so we save the old working directory name // and restore it on complete // Winamp maintains its own concept of a working directory // to help us avoid this problem GetCurrentDirectoryW(MAX_PATH, oldCurPath); // initialize the open file name struct openfilename.lStructSize = sizeof(openfilename); openfilename.hwndOwner = plugin.hwndLibraryParent; openfilename.hInstance = plugin.hDllInstance; openfilename.lpstrFilter = L"ISO Files\0*.iso\0"; openfilename.lpstrCustomFilter = 0; openfilename.nMaxCustFilter = 0; openfilename.nFilterIndex = 0; openfilename.lpstrFile = filename; openfilename.nMaxFile = filenameCch; openfilename.lpstrFileTitle = 0; openfilename.nMaxFileTitle = 0; // we set the initial directory based on winamp's working path openfilename.lpstrInitialDir = WASABI_API_APP->path_getWorkingPath(); openfilename.lpstrTitle = 0; // despite the big note about working directory // we don't want to use OFN_NOCHANGEDIR // because we're going to manually sync Winamp's working path openfilename.Flags = OFN_ENABLESIZING | OFN_EXPLORER | OFN_LONGNAMES; openfilename.nFileOffset = 0; openfilename.nFileExtension = 0; openfilename.lpstrDefExt = L".iso"; openfilename.lCustData = 0; openfilename.lpfnHook = 0; openfilename.lpTemplateName = 0; if (GetSaveFileNameW(&openfilename)) { // let's re-synch Winamp's working directory GetCurrentDirectoryW(MAX_PATH, newCurPath); WASABI_API_APP->path_setWorkingPath(newCurPath); // set the old path back SetCurrentDirectoryW(oldCurPath); return true; // success! } else { // set the old path back SetCurrentDirectoryW(oldCurPath); return false; // user hit cancel or something else happened } } /** ** helper functions ** for creating and deleting ** an iso creator object ** through the wasabi service manager **/ static obj_isocreator *CreateISOCreator() { waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(obj_isocreatorGUID); if (factory) return (obj_isocreator *)factory->getInterface(); else return 0; } static void ReleaseISOCreator(obj_isocreator *creator) { if (creator) { waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(obj_isocreatorGUID); if (factory) factory->releaseInterface(creator); } } void ConvertItemRecordListToISO(const itemRecordList *list) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. isocreator->Open(L"WinampISO", obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); char destinationPath[MAX_PATH]; // loop through the files and add them for (int i=0;iSize;i++) { itemRecord &item = list->Items[i]; // since we have metadata, we're going to auto-generate folders based on the album name const char *album = item.album; if (!album || !*album) album = "Unknown Album"; // isocreator requires a preceding backslash StringCbPrintfA(destinationPath, sizeof(destinationPath), "\\%s\\%s", album, PathFindFileNameA(item.filename)); // convert to unicode since that's what obj_isocreator requires wchar_t unicodeSource[MAX_PATH]; wchar_t unicodeDest[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, item.filename, -1, unicodeSource, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, destinationPath, -1, unicodeDest, MAX_PATH); isocreator->AddFile(unicodeSource, unicodeDest); } isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } void ConvertFilenamesToISO(const char *filenames) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. isocreator->Open(L"WinampISO", obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); wchar_t destinationPath[MAX_PATH]; // loop through the files and add them while (*filenames) { /** ** both playlist loader and iso creator want unicode filenames ** so we'll convert it first */ wchar_t unicodeFilename[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, filenames, -1, unicodeFilename, MAX_PATH); /** ** see if this file is a playlist file ** we'll do that by trying to load it ** the Load() function will fail gracefully if it's not a playlist file ** if it succeeds, it will call loader.OnFile() which adds it to the iso file **/ ISOPlaylistLoader loader(isocreator); // make a callback object for playlist loading if (AGAVE_API_PLAYLISTMANAGER->Load(unicodeFilename, &loader) == PLAYLISTMANAGER_LOAD_NO_LOADER) { // not a playlist file, so load it normally // isocreator requires a preceding backslash StringCbPrintfW(destinationPath, sizeof(destinationPath), L"\\%s", PathFindFileNameW(unicodeFilename)); isocreator->AddFile(unicodeFilename, destinationPath); } filenames+=strlen(filenames)+1; } isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } /** ** Load Playlist and write it to the ISO file ** this function is a bit complex, since we have to load the playlist ** through api_playlistmanager. This involves creating an playlist loader callback ** (ifc_playlistloadercallback) which gets called for each playlist item **/ void ConvertPlaylistToISO(const mlPlaylist *playlist) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. const wchar_t *title=L"WinampISO"; if (playlist->title) // if there's a playlist title, use it as the volume name title = playlist->title; isocreator->Open(title, obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); ISOPlaylistLoader loader(isocreator); // make a callback object for playlist loading AGAVE_API_PLAYLISTMANAGER->Load(playlist->filename, &loader); isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } /** Load all playlists and write them to the ISO file ** this function is a bit complex, since we have to load the playlist ** through api_playlistmanager. This involves creating an playlist loader callback ** (ifc_playlistloadercallback) which gets called for each playlist item **/ void ConvertPlaylistsToISO(const mlPlaylist **playlists) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. isocreator->Open(L"WinampISO", obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); while (*playlists) { const mlPlaylist *playlist = *playlists; ISOPlaylistLoader loader(isocreator); // make a callback object for playlist loading AGAVE_API_PLAYLISTMANAGER->Load(playlist->filename, &loader); playlists++; } isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } void ConvertUnicodeItemRecordListToISO(const itemRecordListW *list) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. isocreator->Open(L"WinampISO", obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); wchar_t destinationPath[MAX_PATH]; // loop through the files and add them for (int i=0;iSize;i++) { itemRecordW &item = list->Items[i]; // since we have metadata, we're going to auto-generate folders based on the album name const wchar_t *album = item.album; if (!album || !*album) album = L"Unknown Album"; // isocreator requires a preceding backslash StringCbPrintfW(destinationPath, sizeof(destinationPath), L"\\%s\\%s", album, PathFindFileNameW(item.filename)); isocreator->AddFile(item.filename, destinationPath); } isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } void ConvertUnicodeFilenamesToISO(const wchar_t *filenames) { obj_isocreator *isocreator = CreateISOCreator(); if (isocreator) { wchar_t destination[MAX_PATH]; if (PromptForFilename(destination, MAX_PATH)) { // these values are hardcoded for this example. isocreator->Open(L"WinampISO", obj_isocreator::FORMAT_JOLIET, obj_isocreator::MEDIA_CD); wchar_t destinationPath[MAX_PATH]; // loop through the files and add them while (*filenames) { /** ** see if this file is a playlist file ** we'll do that by trying to load it ** the Load() function will fail gracefully if it's not a playlist file ** if it succeeds, it will call loader.OnFile() which adds it to the iso file **/ ISOPlaylistLoader loader(isocreator); // make a callback object for playlist loading if (AGAVE_API_PLAYLISTMANAGER->Load(filenames, &loader) == PLAYLISTMANAGER_LOAD_NO_LOADER) { // not a playlist file, so load it normally // isocreator requires a preceding backslash StringCbPrintfW(destinationPath, sizeof(destinationPath), L"\\%s", PathFindFileNameW(filenames)); isocreator->AddFile(filenames, destinationPath); } filenames+=wcslen(filenames)+1; } isocreator->Write(destination, 0); } ReleaseISOCreator(isocreator); } } /* --- Playlist Loader definition --- */ ISOPlaylistLoader::ISOPlaylistLoader(obj_isocreator *_creator) { creator=_creator; } void ISOPlaylistLoader::OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info) { // isocreator requires a preceding backslash wchar_t destinationPath[MAX_PATH]; StringCbPrintfW(destinationPath, sizeof(destinationPath), L"\\%s", PathFindFileNameW(filename)); // add file to .iso image creator->AddFile(filename, destinationPath); } #define CBCLASS ISOPlaylistLoader START_DISPATCH; VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile) //VCB(IFC_PLAYLISTLOADERCALLBACK_ONPLAYLISTINFO, OnPlaylistInfo) END_DISPATCH;