From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/SDK/ml_iso/ToISO.cpp | 366 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 Src/Plugins/SDK/ml_iso/ToISO.cpp (limited to 'Src/Plugins/SDK/ml_iso/ToISO.cpp') diff --git a/Src/Plugins/SDK/ml_iso/ToISO.cpp b/Src/Plugins/SDK/ml_iso/ToISO.cpp new file mode 100644 index 00000000..1a5e132f --- /dev/null +++ b/Src/Plugins/SDK/ml_iso/ToISO.cpp @@ -0,0 +1,366 @@ +#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; -- cgit