aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/SDK/ml_iso/ToISO.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/SDK/ml_iso/ToISO.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/SDK/ml_iso/ToISO.cpp')
-rw-r--r--Src/Plugins/SDK/ml_iso/ToISO.cpp366
1 files changed, 366 insertions, 0 deletions
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 <api/service/waservicefactory.h>
+#include "../burner/obj_isocreator.h"
+#include "../playlist/ifc_playlistloadercallback.h"
+#include <shlwapi.h>
+#include <strsafe.h>
+
+/**
+** 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;i<list->Size;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;i<list->Size;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;