aboutsummaryrefslogtreecommitdiff
path: root/Src/Agave
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Agave')
-rw-r--r--Src/Agave/Agave.h22
-rw-r--r--Src/Agave/AlbumArt/api_albumart.cpp1
-rw-r--r--Src/Agave/AlbumArt/api_albumart.h124
-rw-r--r--Src/Agave/AlbumArt/svc_albumArtProvider.h73
-rw-r--r--Src/Agave/Component/ifc_wa5component.h43
-rw-r--r--Src/Agave/Config/api_config.h135
-rw-r--r--Src/Agave/Config/ifc_configgroup.h36
-rw-r--r--Src/Agave/Config/ifc_configitem.h200
-rw-r--r--Src/Agave/DecodeFile/api_decodefile.h104
-rw-r--r--Src/Agave/DecodeFile/ifc_audiostream.h65
-rw-r--r--Src/Agave/DecodeFile/ifc_raw_media_reader.h26
-rw-r--r--Src/Agave/DecodeFile/svc_raw_media_reader.h32
-rw-r--r--Src/Agave/Encode/ifc_audioFileEncoder.h60
-rw-r--r--Src/Agave/Encode/notes.txt23
-rw-r--r--Src/Agave/Encode/svc_audioFileEncoder.h64
-rw-r--r--Src/Agave/ExplorerFindFile/api_explorerfindfile.h46
-rw-r--r--Src/Agave/Language/api_language.h330
-rw-r--r--Src/Agave/Language/lang.h643
-rw-r--r--Src/Agave/Metadata/api_metadata.cpp1
-rw-r--r--Src/Agave/Metadata/api_metadata.h102
-rw-r--r--Src/Agave/Metadata/ifc_metadataReader.h107
-rw-r--r--Src/Agave/Metadata/svc_metatag.h152
-rw-r--r--Src/Agave/PlaylistColouriser/api_playlist_colouriser.h154
-rw-r--r--Src/Agave/Queue/api_queue.h202
-rw-r--r--Src/Agave/Random/api_random.h78
-rw-r--r--Src/Agave/URIHandler/svc_urihandler.h63
26 files changed, 2886 insertions, 0 deletions
diff --git a/Src/Agave/Agave.h b/Src/Agave/Agave.h
new file mode 100644
index 00000000..278d6db1
--- /dev/null
+++ b/Src/Agave/Agave.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <api/service/waServiceFactory.h>
+#include <api/service/api_service.h>
+#include <api/application/api_application.h>
+#include <api/syscb/api_syscb.h>
+#include <api/memmgr/api_memmgr.h>
+#include "./Metadata/api_metadata.h"
+#include "./Language/api_language.h"
+#include "../Plugins/Library/ml_local/api_mldb.h"
+#include "../ombrowser/obj_ombrowser.h"
+#include "../Winamp/JSAPI2_api_security.h"
+#include "./Config/api_config.h"
+#include "./AlbumArt/api_albumart.h"
+#include "../playlist/api_playlistmanager.h"
+#include "../nu/threadpool/api_threadpool.h"
+#include "../devices/api_devicemanager.h"
+#include "../Winamp/api_stats.h"
+#include "../Plugins/Library/ml_wire/api_podcasts.h"
+#include "../Plugins/Library/ml_impex/api_importer.h"
+#include "../Plugins/Library/ml_plg/api_playlist_generator.h"
+#include "./ExplorerFindFile/api_explorerfindfile.h"
diff --git a/Src/Agave/AlbumArt/api_albumart.cpp b/Src/Agave/AlbumArt/api_albumart.cpp
new file mode 100644
index 00000000..93beabf5
--- /dev/null
+++ b/Src/Agave/AlbumArt/api_albumart.cpp
@@ -0,0 +1 @@
+#include "api_albumart.h"
diff --git a/Src/Agave/AlbumArt/api_albumart.h b/Src/Agave/AlbumArt/api_albumart.h
new file mode 100644
index 00000000..256c8dc1
--- /dev/null
+++ b/Src/Agave/AlbumArt/api_albumart.h
@@ -0,0 +1,124 @@
+#ifndef NULLSOFT_WINAMP_API_ALBUMART_H
+#define NULLSOFT_WINAMP_API_ALBUMART_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include <api/service/services.h>
+
+enum
+{
+ ALBUMART_SUCCESS = 0,
+ ALBUMART_FAILURE = 1,
+};
+
+enum
+{
+ ALBUMART_NONE = 0,
+ ALBUMART_EMBEDDED = 1,
+ ALBUMART_ALBUM = 2,
+ ALBUMART_NFO = 3,
+ ALBUMART_FILENAME = 4,
+ ALBUMART_FOLDER = 5,
+ ALBUMART_FRONT = 6,
+ ALBUMART_ARTWORK = 7,
+};
+
+class api_albumart : public Dispatchable
+{
+protected:
+ api_albumart(){}
+ ~api_albumart(){}
+public:
+ static FOURCC getServiceType() { return WaSvc::UNIQUE; }
+ // use WASABI_API_MEMMGR->sysFree on the bits you get back from here.
+ // if this function fails (return value != ALBUMART_SUCCESS), there is no guarantee about the values
+ // in w, h or bits. please, please, please don't check bits == 0 for success/failure
+ int GetAlbumArt(const wchar_t *filename, const wchar_t *type, int *w, int *h, ARGB32 **bits);
+ // hack alert
+ int GetAlbumArt_NoAMG(const wchar_t *filename, const wchar_t *type, int *w, int *h, ARGB32 **bits);
+ // use to get still-compressed data
+ int GetAlbumArtData(const wchar_t *filename, const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType);
+ // use to get the origin of the artwork for the file, e.g. folder, embedded
+ int GetAlbumArtOrigin(const wchar_t *filename, const wchar_t *type, wchar_t **mimeType);
+
+ // use WASABI_API_MEMMGR->sysFree to free types
+ int GetAlbumArtTypes(const wchar_t *filename, wchar_t **types);
+
+ int GetValidAlbumArtTypes(const wchar_t *filename, wchar_t **types);
+
+ // returns ALBUMART_SUCCESS or ALBUMART_FAILURE
+ // if mimeType is NULL, bits is ARGB32. w and h are not used for mimeTypes where the dimentions are in the data
+ // if bits is NULL, this removes albumart.
+ int SetAlbumArt(const wchar_t *filename, const wchar_t *type, int w, int h, const void *bits, size_t len, const wchar_t *mimeType);
+
+ int DeleteAlbumArt(const wchar_t *filename, const wchar_t *type);
+
+ // copies all album art from one file to another
+ // also copies bits like folder.jpg if the two files live in different places
+ // if you don't like the logic of this function, implement your own using svc_albumArtProvider directly
+ int CopyAlbumArt(const wchar_t *sourceFilename, const wchar_t *destinationFilename);
+ DISPATCH_CODES
+ {
+ API_ALBUMART_GETALBUMART = 10,
+ API_ALBUMART_GETALBUMART_NOAMG = 11,
+ API_ALBUMART_GETALBUMARTDATA = 12,
+ API_ALBUMART_GETALBUMARTORIGIN = 13,
+ API_ALBUMART_GETALBUMARTTYPES = 20,
+ API_ALBUMART_GETVALIDALBUMARTTYPES = 30,
+ API_ALBUMART_SETALBUMART = 40,
+ API_ALBUMART_DELETEALBUMART = 50,
+ API_ALBUMART_COPYALBUMART = 60,
+ };
+};
+
+inline int api_albumart::GetAlbumArt(const wchar_t *filename, const wchar_t *type, int *w, int *h, ARGB32 **bits)
+{
+ return _call(API_ALBUMART_GETALBUMART, (int)ALBUMART_FAILURE, filename, type, w, h, bits);
+}
+
+inline int api_albumart::GetAlbumArt_NoAMG(const wchar_t *filename, const wchar_t *type, int *w, int *h, ARGB32 **bits)
+{
+ return _call(API_ALBUMART_GETALBUMART_NOAMG, (int)ALBUMART_FAILURE, filename, type, w, h, bits);
+}
+
+inline int api_albumart::GetAlbumArtData(const wchar_t *filename, const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType)
+{
+ return _call(API_ALBUMART_GETALBUMARTDATA, (int)ALBUMART_FAILURE, filename, type, bits, len, mimeType);
+}
+
+inline int api_albumart::GetAlbumArtOrigin(const wchar_t *filename, const wchar_t *type, wchar_t **mimeType)
+{
+ return _call(API_ALBUMART_GETALBUMARTORIGIN, (int)ALBUMART_FAILURE, filename, type, mimeType);
+}
+
+inline int api_albumart::GetAlbumArtTypes(const wchar_t *filename, wchar_t **types)
+{
+ return _call(API_ALBUMART_GETALBUMARTTYPES, (int)ALBUMART_FAILURE, filename, types);
+}
+
+inline int api_albumart::GetValidAlbumArtTypes(const wchar_t *filename, wchar_t **types)
+{
+ return _call(API_ALBUMART_GETVALIDALBUMARTTYPES, (int)ALBUMART_FAILURE, filename, types);
+}
+
+inline int api_albumart::SetAlbumArt(const wchar_t *filename, const wchar_t *type, int w, int h, const void *bits, size_t len, const wchar_t *mimeType)
+{
+ return _call(API_ALBUMART_SETALBUMART, (int)ALBUMART_FAILURE, filename, type, w, h, bits, len, mimeType);
+}
+
+inline int api_albumart::DeleteAlbumArt(const wchar_t *filename, const wchar_t *type)
+{
+ return _call(API_ALBUMART_DELETEALBUMART, (int)ALBUMART_FAILURE, filename, type);
+}
+
+inline int api_albumart::CopyAlbumArt(const wchar_t *sourceFilename, const wchar_t *destinationFilename)
+{
+ return _call(API_ALBUMART_COPYALBUMART, (int)ALBUMART_FAILURE, sourceFilename, destinationFilename);
+}
+
+// {AC4C4468-F91F-41f3-A5FA-E2B81DC6EB3A}
+static const GUID albumArtGUID =
+{ 0xac4c4468, 0xf91f, 0x41f3, { 0xa5, 0xfa, 0xe2, 0xb8, 0x1d, 0xc6, 0xeb, 0x3a } };
+
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/AlbumArt/svc_albumArtProvider.h b/Src/Agave/AlbumArt/svc_albumArtProvider.h
new file mode 100644
index 00000000..3dbc2a2f
--- /dev/null
+++ b/Src/Agave/AlbumArt/svc_albumArtProvider.h
@@ -0,0 +1,73 @@
+#ifndef NULLSOFT_AGAVE_SVC_ALBUMARTPROVIDER_H
+#define NULLSOFT_AGAVE_SVC_ALBUMARTPROVIDER_H
+
+#include <bfc/dispatch.h>
+#include <bfc/std_mkncc.h> // for MKnCC()
+
+enum
+{
+ ALBUMARTPROVIDER_SUCCESS = 0,
+ ALBUMARTPROVIDER_FAILURE = 1,
+ ALBUMARTPROVIDER_READONLY = 2,
+
+ ALBUMARTPROVIDER_TYPE_EMBEDDED = 0, // contained within another file (e.g. inside id3v2 tag)
+ ALBUMARTPROVIDER_TYPE_DATABASE = 1, // cached in a database somewhere (e.g. ipod artwork DB)
+ ALBUMARTPROVIDER_TYPE_FOLDER = 2, // sitting on a folder somewhere (e.g. folder.jpg)
+};
+class svc_albumArtProvider : public Dispatchable
+{
+protected:
+ svc_albumArtProvider() {}
+ ~svc_albumArtProvider() {}
+public:
+
+ static FOURCC getServiceType() { return svc_albumArtProvider::SERVICETYPE; }
+ bool IsMine(const wchar_t *filename);
+ int ProviderType();
+ // implementation note: use WASABI_API_MEMMGR to alloc bits and mimetype, so that the recipient can free through that
+ int GetAlbumArtData(const wchar_t *filename, const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType);
+ int SetAlbumArtData(const wchar_t *filename, const wchar_t *type, void *bits, size_t len, const wchar_t *mimeType);
+ int DeleteAlbumArt(const wchar_t *filename, const wchar_t *type);
+
+ DISPATCH_CODES
+ {
+ SVC_ALBUMARTPROVIDER_PROVIDERTYPE = 0,
+ SVC_ALBUMARTPROVIDER_GETALBUMARTDATA = 10,
+ SVC_ALBUMARTPROVIDER_ISMINE = 20,
+ SVC_ALBUMARTPROVIDER_SETALBUMARTDATA = 30,
+ SVC_ALBUMARTPROVIDER_DELETEALBUMART = 40,
+ };
+
+ enum
+ {
+ SERVICETYPE = MK3CC('a','a','p')
+ };
+
+};
+
+inline bool svc_albumArtProvider::IsMine(const wchar_t *filename)
+{
+ return _call(SVC_ALBUMARTPROVIDER_ISMINE, false, filename);
+}
+
+inline int svc_albumArtProvider::ProviderType()
+{
+ return _call(SVC_ALBUMARTPROVIDER_PROVIDERTYPE, (int)ALBUMARTPROVIDER_TYPE_EMBEDDED);
+}
+
+inline int svc_albumArtProvider::GetAlbumArtData(const wchar_t *filename, const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType)
+{
+ return _call(SVC_ALBUMARTPROVIDER_GETALBUMARTDATA, (int)ALBUMARTPROVIDER_FAILURE, filename, type, bits, len, mimeType);
+}
+
+inline int svc_albumArtProvider::SetAlbumArtData(const wchar_t *filename, const wchar_t *type, void *bits, size_t len, const wchar_t *mimeType)
+{
+ return _call(SVC_ALBUMARTPROVIDER_SETALBUMARTDATA, (int)ALBUMARTPROVIDER_FAILURE, filename, type, bits, len, mimeType);
+}
+
+inline int svc_albumArtProvider::DeleteAlbumArt(const wchar_t *filename, const wchar_t *type)
+{
+ return _call(SVC_ALBUMARTPROVIDER_DELETEALBUMART, (int)ALBUMARTPROVIDER_FAILURE, filename, type);
+}
+
+#endif
diff --git a/Src/Agave/Component/ifc_wa5component.h b/Src/Agave/Component/ifc_wa5component.h
new file mode 100644
index 00000000..fb0a1b54
--- /dev/null
+++ b/Src/Agave/Component/ifc_wa5component.h
@@ -0,0 +1,43 @@
+#ifndef __WASABI_IFC_WA5COMPONENT_H_
+#define __WASABI_IFC_WA5COMPONENT_H_
+
+#include <bfc/dispatch.h>
+
+class api_service;
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+class NOVTABLE ifc_wa5component : public Dispatchable
+{
+public:
+ DISPATCH_CODES
+ {
+ API_WA5COMPONENT_REGISTERSERVICES = 10,
+ API_WA5COMPONENT_REGISTERSERVICES_SAFE_MODE = 15,
+ API_WA5COMPONENT_DEREEGISTERSERVICES = 20,
+ };
+
+ void RegisterServices( api_service *service );
+ void DeregisterServices( api_service *service );
+
+#ifdef WIN32
+ HMODULE hModule;
+#else
+ void *dlLibrary; // pointer returned from dlopen
+#endif
+};
+
+inline void ifc_wa5component::RegisterServices( api_service *service )
+{
+ _voidcall( API_WA5COMPONENT_REGISTERSERVICES, service );
+}
+
+inline void ifc_wa5component::DeregisterServices( api_service *service )
+{
+ _voidcall( API_WA5COMPONENT_DEREEGISTERSERVICES, service );
+}
+
+extern "C" typedef ifc_wa5component *(*GETCOMPONENT_FUNC)();
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Config/api_config.h b/Src/Agave/Config/api_config.h
new file mode 100644
index 00000000..d71885d6
--- /dev/null
+++ b/Src/Agave/Config/api_config.h
@@ -0,0 +1,135 @@
+#ifndef NULLSOFT_AGAVE_API_CONFIG_H
+#define NULLSOFT_AGAVE_API_CONFIG_H
+
+#include "bfc/dispatch.h"
+
+#include "ifc_configgroup.h"
+
+enum
+{
+ CONFIG_SUCCESS = 0,
+ CONFIG_FAILURE = 1,
+ CONFIG_GROUPNOTFOUND = 2,
+ CONFIG_ITEMNOTFOUND = 3,
+};
+
+class api_config : public Dispatchable
+{
+protected:
+ api_config() {}
+ ~api_config() {}
+
+public:
+ ifc_configgroup *GetGroup( GUID groupGUID );
+ void RegisterGroup( ifc_configgroup *newGroup );
+
+ /* Shortcut methods */
+ bool GetBool( GUID groupGUID, const wchar_t *configItem, bool defaultValue );
+ uintptr_t GetUnsigned( GUID groupGUID, const wchar_t *configItem, uintptr_t defaultValue );
+ intptr_t GetInt( GUID groupGUID, const wchar_t *configItem, intptr_t defaultValue );
+ float GetFloat( GUID groupGUID, const wchar_t *configItem, float defaultValue );
+ const wchar_t *GetString( GUID groupGUID, const wchar_t *configItem, const wchar_t *defaultValue );
+ ifc_configitem *GetItem( GUID groupGUID, const wchar_t *configItem );
+
+ DISPATCH_CODES
+ {
+ API_CONFIG_GETGROUP = 10,
+ API_CONFIG_REGISTERGROUP = 20,
+ };
+};
+
+inline ifc_configgroup *api_config::GetGroup( GUID groupGUID )
+{
+ return _call( API_CONFIG_GETGROUP, (ifc_configgroup *)0, groupGUID );
+}
+
+inline void api_config::RegisterGroup( ifc_configgroup *newGroup )
+{
+ _voidcall( API_CONFIG_REGISTERGROUP, newGroup );
+}
+
+inline bool api_config::GetBool( GUID groupGUID, const wchar_t *configItem, bool defaultValue )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ {
+ ifc_configitem *item = group->GetItem( configItem );
+ if ( item )
+ return item->GetBool();
+ }
+
+ return defaultValue;
+}
+
+inline uintptr_t api_config::GetUnsigned( GUID groupGUID, const wchar_t *configItem, uintptr_t defaultValue )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ {
+ ifc_configitem *item = group->GetItem( configItem );
+ if ( item )
+ return item->GetUnsigned();
+ }
+
+ return defaultValue;
+}
+
+inline intptr_t api_config::GetInt( GUID groupGUID, const wchar_t *configItem, intptr_t defaultValue )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ {
+ ifc_configitem *item = group->GetItem( configItem );
+ if ( item )
+ return item->GetInt();
+ }
+
+ return defaultValue;
+}
+
+inline float api_config::GetFloat( GUID groupGUID, const wchar_t *configItem, float defaultValue )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ {
+ ifc_configitem *item = group->GetItem( configItem );
+ if ( item )
+ return item->GetFloat();
+ }
+
+ return defaultValue;
+}
+
+inline const wchar_t *api_config::GetString( GUID groupGUID, const wchar_t *configItem, const wchar_t *defaultValue )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ {
+ ifc_configitem *item = group->GetItem( configItem );
+ if ( item )
+ return item->GetString();
+ }
+
+ return defaultValue;
+}
+
+inline ifc_configitem *api_config::GetItem( GUID groupGUID, const wchar_t *configItem )
+{
+ ifc_configgroup *group = GetGroup( groupGUID );
+ if ( group )
+ return group->GetItem( configItem );
+
+ return 0;
+}
+
+// {AEFBF8BE-E0AA-4318-8CC1-4353410B64DC}
+static const GUID AgaveConfigGUID =
+{ 0xaefbf8be, 0xe0aa, 0x4318, { 0x8c, 0xc1, 0x43, 0x53, 0x41, 0xb, 0x64, 0xdc } };
+
+extern api_config *configApi;
+
+#ifndef AGAVE_API_CONFIG
+#define AGAVE_API_CONFIG configApi
+#endif // !AGAVE_API_CONFIG
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Config/ifc_configgroup.h b/Src/Agave/Config/ifc_configgroup.h
new file mode 100644
index 00000000..20554865
--- /dev/null
+++ b/Src/Agave/Config/ifc_configgroup.h
@@ -0,0 +1,36 @@
+#ifndef NULLSOFT_AGAVE_IFC_CONFIGGROUP_H
+#define NULLSOFT_AGAVE_IFC_CONFIGGROUP_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include <bfc/platform/guid.h>
+#include "ifc_configitem.h"
+
+class ifc_configgroup : public Dispatchable
+{
+protected:
+ ifc_configgroup() {}
+ ~ifc_configgroup() {}
+
+public:
+ ifc_configitem *GetItem( const wchar_t *name );
+ GUID GetGUID();
+
+ DISPATCH_CODES
+ {
+ IFC_CONFIGGROUP_GETITEM = 10,
+ IFC_CONFIGGROUP_GETGUID = 20,
+ };
+
+};
+
+inline ifc_configitem *ifc_configgroup::GetItem(const wchar_t *name)
+{
+ return _call(IFC_CONFIGGROUP_GETITEM, (ifc_configitem *)0, name);
+}
+
+inline GUID ifc_configgroup::GetGUID()
+{
+ return _call(IFC_CONFIGGROUP_GETGUID, (GUID)INVALID_GUID);
+}
+#endif \ No newline at end of file
diff --git a/Src/Agave/Config/ifc_configitem.h b/Src/Agave/Config/ifc_configitem.h
new file mode 100644
index 00000000..7a0f5180
--- /dev/null
+++ b/Src/Agave/Config/ifc_configitem.h
@@ -0,0 +1,200 @@
+#ifndef NULLSOFT_AGAVE_IFC_CONFIGITEM_H
+#define NULLSOFT_AGAVE_IFC_CONFIGITEM_H
+
+#include <bfc/dispatch.h>
+#include <stddef.h>
+/*
+notes:
+The Set() functions are "public-facing", meaning that they can be called by anyone. If you want to make your config item read-only,
+then simply don't implement these. You can always make "private" Set functions in your implementation.
+
+SetStringInternal and GetStringInternal are written for use with classes to load and save from INI files (or XML files or whatever).
+It's up to you to figure out a clever way to encode yourself.
+
+*/
+
+enum
+{
+ CONFIG_ITEM_TYPE_STRING = 0,
+ CONFIG_ITEM_TYPE_INT = 1,
+ CONFIG_ITEM_TYPE_UNSIGNED =2,
+ CONFIG_ITEM_TYPE_BOOL =3,
+ CONFIG_ITEM_TYPE_BINARY =4,
+ CONFIG_ITEM_TYPE_INT_ARRAY = 5,
+};
+
+class ifc_configitem : public Dispatchable
+{
+protected:
+ ifc_configitem() {}
+ ~ifc_configitem() {}
+public:
+ const wchar_t *GetName();
+ int GetType();
+
+ const wchar_t *GetString();
+ void SetString(const wchar_t *stringValue);
+
+ intptr_t GetInt();
+ void SetInt(intptr_t intValue);
+
+ uintptr_t GetUnsigned();
+ void SetUnsigned(uintptr_t unsignedValue);
+
+ bool GetBool();
+ void SetBool(bool boolValue);
+
+ float GetFloat();
+ void SetFloat(float floatValue);
+
+ size_t GetBinarySize();
+ size_t GetBinaryData(void *data, size_t bytes); // returns bytes written
+ void SetBinaryData(void *data, size_t bytes);
+
+ size_t GetIntArrayElements();
+ size_t GetIntArray(intptr_t *array, size_t elements); // returns elements written
+ void SetIntArray(intptr_t *array, size_t elements);
+
+ const wchar_t *GetStringInternal(); // gets a string suitable for saving in an INI file or XML
+ void SetStringInternal(const wchar_t *internalString);
+
+public:
+ DISPATCH_CODES
+ {
+ IFC_CONFIGITEM_GETNAME = 10,
+ IFC_CONFIGITEM_GETTYPE = 20,
+
+ IFC_CONFIGITEM_GETSTRING= 30,
+ IFC_CONFIGITEM_SETSTRING= 40,
+
+ IFC_CONFIGITEM_GETINT= 50,
+ IFC_CONFIGITEM_SETINT= 60,
+
+ IFC_CONFIGITEM_GETUNSIGNED= 70,
+ IFC_CONFIGITEM_SETUNSIGNED= 80,
+
+ IFC_CONFIGITEM_GETBOOL= 90,
+ IFC_CONFIGITEM_SETBOOL= 100,
+
+ IFC_CONFIGITEM_GETBINARYSIZE= 110,
+ IFC_CONFIGITEM_GETBINARYDATA= 120,
+ IFC_CONFIGITEM_SETBINARYDATA= 130,
+
+ IFC_CONFIGITEM_GETINTARRAYELEMENTS= 140,
+ IFC_CONFIGITEM_GETINTARRAY= 150,
+ IFC_CONFIGITEM_SETINTARRAY= 160,
+
+ IFC_CONFIGITEM_GETSTRINGINTERNAL= 170,
+ IFC_CONFIGITEM_SETSTRINGINTERNAL= 180,
+
+ IFC_CONFIGITEM_GETFLOAT= 190,
+ IFC_CONFIGITEM_SETFLOAT= 200,
+ };
+};
+
+
+
+inline const wchar_t *ifc_configitem::GetName()
+{
+ return _call(IFC_CONFIGITEM_GETNAME, (const wchar_t *)0);
+}
+
+inline int ifc_configitem::GetType()
+{
+ return _call(IFC_CONFIGITEM_GETTYPE, (int)0);
+}
+
+inline const wchar_t *ifc_configitem::GetString()
+{
+ return _call(IFC_CONFIGITEM_GETSTRING, (const wchar_t *)0);
+}
+
+inline void ifc_configitem::SetString(const wchar_t *stringValue)
+{
+ _voidcall(IFC_CONFIGITEM_SETSTRING, stringValue);
+}
+
+
+inline intptr_t ifc_configitem::GetInt()
+{
+ return _call(IFC_CONFIGITEM_GETINT, (intptr_t)0);
+}
+#pragma warning(push)
+#pragma warning(disable: 4244)
+inline void ifc_configitem::SetInt(intptr_t intValue)
+{
+ _voidcall(IFC_CONFIGITEM_SETINT, intValue);
+}
+#pragma warning(pop)
+
+inline uintptr_t ifc_configitem::GetUnsigned()
+{
+ return _call(IFC_CONFIGITEM_GETUNSIGNED, (uintptr_t)0);
+}
+
+inline void ifc_configitem::SetUnsigned(uintptr_t unsignedValue)
+{
+ _voidcall(IFC_CONFIGITEM_SETUNSIGNED, unsignedValue);
+}
+
+
+inline bool ifc_configitem::GetBool()
+{
+ return _call(IFC_CONFIGITEM_GETBOOL, (bool)false);
+}
+
+inline void ifc_configitem::SetBool(bool boolValue)
+{
+ _voidcall(IFC_CONFIGITEM_SETBOOL, boolValue);
+}
+
+inline size_t ifc_configitem::GetBinarySize()
+{
+ return _call(IFC_CONFIGITEM_GETBINARYSIZE, (size_t)0);
+}
+
+inline size_t ifc_configitem::GetBinaryData(void *data, size_t bytes)
+{
+ return _call(IFC_CONFIGITEM_GETBINARYDATA, (size_t)0, data, bytes);
+}
+
+inline void ifc_configitem::SetBinaryData(void *data, size_t bytes)
+{
+ _voidcall(IFC_CONFIGITEM_SETBINARYDATA, data, bytes);
+}
+
+inline size_t ifc_configitem::GetIntArrayElements()
+{
+ return _call(IFC_CONFIGITEM_GETINTARRAYELEMENTS, (size_t)0);
+}
+
+inline size_t ifc_configitem::GetIntArray(intptr_t *array, size_t elements)
+{
+ return _call(IFC_CONFIGITEM_GETINTARRAY, (size_t)0, array, elements);
+}
+inline void ifc_configitem::SetIntArray(intptr_t *array, size_t elements)
+{
+ _voidcall(IFC_CONFIGITEM_SETINTARRAY, array, elements);
+}
+
+inline const wchar_t *ifc_configitem::GetStringInternal()
+{
+ return _call(IFC_CONFIGITEM_GETSTRINGINTERNAL, (const wchar_t *)0);
+}
+inline void ifc_configitem::SetStringInternal(const wchar_t *internalString)
+{
+ _voidcall(IFC_CONFIGITEM_SETSTRINGINTERNAL, internalString);
+}
+
+inline float ifc_configitem::GetFloat()
+{
+ return _call(IFC_CONFIGITEM_GETFLOAT, (float)0);
+}
+
+inline void ifc_configitem::SetFloat(float floatValue)
+{
+ _voidcall(IFC_CONFIGITEM_SETFLOAT, floatValue);
+}
+
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/DecodeFile/api_decodefile.h b/Src/Agave/DecodeFile/api_decodefile.h
new file mode 100644
index 00000000..c2b3c46a
--- /dev/null
+++ b/Src/Agave/DecodeFile/api_decodefile.h
@@ -0,0 +1,104 @@
+#ifndef NULLSOFT_AGAVE_API_DECODEFILE_H
+#define NULLSOFT_AGAVE_API_DECODEFILE_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include "ifc_audiostream.h"
+
+enum
+{
+ API_DECODEFILE_SUCCESS = 0,
+ API_DECODEFILE_FAILURE = 1,
+
+ API_DECODEFILE_UNSUPPORTED = 2, // type is unsupported
+ API_DECODEFILE_NO_INTERFACE = 3, // type is supported, but plugin does provide any interfaces for direct decoding
+ API_DECODEFILE_WINAMP_PRO = 4, // user has to pay $$$ to do this
+ API_DECODEFILE_NO_RIGHTS = 5, // user is not allowed to decode this file (e.g. DRM)
+ API_DECODEFILE_BAD_RESAMPLE = 6, // Winamp is unable to resample this file to CDDA format (stereo 16bit 44.1kHz)
+ API_DECODEFILE_FAIL_NO_WARN = 7, // we have already informed the user of an issue so do not show again e.g. CD playing so cannot also do a rip
+};
+
+enum
+{
+ AUDIOPARAMETERS_FLOAT = 1,
+ AUDIOPARAMETERS_MAXCHANNELS = 2, // set this if channels is meant to define an upper limit
+ // (e.g. setting channels=2 and flags |= AUDIOPARAMETERS_MAXCHANNELS means 1 or 2 channels is OK, but not more)
+ AUDIOPARAMETERS_MAXSAMPLERATE = 4, // like AUDIOPARAMETERS_MAXCHANNELS but for sample rate
+ AUDIOPARAMETERS_NON_INTERLEAVED = 8, // audio data is stored as separate buffers per channel. not currently implemented
+};
+
+struct AudioParameters
+{
+public:
+ AudioParameters() : bitsPerSample(0), channels(0), sampleRate(0), sampleRateReal(0.f), flags(0), sizeBytes((size_t) - 1), errorCode(API_DECODEFILE_SUCCESS)
+ {}
+ uint32_t bitsPerSample;
+ uint32_t channels;
+ uint32_t sampleRate;
+ float sampleRateReal; // yes this is duplicate.
+ int flags;
+ size_t sizeBytes; // total size of decoded file, (size_t)-1 means don't know
+ int errorCode;
+};
+
+class api_decodefile : public Dispatchable
+{
+public:
+ /* OpenAudioBackground gives you back an ifc_audiostream that you can use to get decompressed bits
+ * if it returns 0, check parameters->errorCode for the failure reason
+ * fill parameters with desired values (0 if you don't care)
+ * the decoder will _do its best_ to satisfy your passed-in audio parameters
+ * but this API does not guarantee them, so be sure to check the parameters struct after the function returns
+ * it's **UP TO YOU** to do any necessary conversion (sample rate, channels, bits-per-sample) if the decoder can't do it
+ */
+ ifc_audiostream *OpenAudioBackground(const wchar_t *filename, AudioParameters *parameters);
+ /* OpenAudio is the same as OpenAudioBackground
+ * but, it will use the input plugin system to decode if necessary
+ * so it's best to use this in a separate winamp.exe
+ * to be honest, it was designed for internal use in the CD burner
+ * so it's best not to use this one at all
+ */
+ ifc_audiostream *OpenAudio(const wchar_t *filename, AudioParameters *parameters);
+
+ void CloseAudio(ifc_audiostream *audioStream);
+ /* verifies that a decoder exists to decompress this filename.
+ this is not a guarantee that the file is openable, just that it can be matched to a decoder */
+ bool DecoderExists(const wchar_t *filename);
+
+public:
+ DISPATCH_CODES
+ {
+ API_DECODEFILE_OPENAUDIO = 10,
+ API_DECODEFILE_OPENAUDIO2 = 11,
+ API_DECODEFILE_CLOSEAUDIO = 20,
+ API_DECODEFILE_DECODEREXISTS = 30,
+ };
+};
+
+inline ifc_audiostream *api_decodefile::OpenAudio(const wchar_t *filename, AudioParameters *parameters)
+{
+ return _call(API_DECODEFILE_OPENAUDIO, (ifc_audiostream *)0, filename, parameters);
+}
+
+inline ifc_audiostream *api_decodefile::OpenAudioBackground(const wchar_t *filename, AudioParameters *parameters)
+{
+ return _call(API_DECODEFILE_OPENAUDIO2, (ifc_audiostream *)0, filename, parameters);
+}
+
+inline void api_decodefile::CloseAudio(ifc_audiostream *audioStream)
+{
+ _voidcall(API_DECODEFILE_CLOSEAUDIO, audioStream);
+}
+
+inline bool api_decodefile::DecoderExists(const wchar_t *filename)
+{
+ return _call(API_DECODEFILE_DECODEREXISTS, (bool)true, filename); // we default to true so that an old implementation doesn't break completely
+}
+
+// {9B4188F5-4295-48ab-B50C-F2B0BB56D242}
+static const GUID decodeFileGUID =
+{
+ 0x9b4188f5, 0x4295, 0x48ab, { 0xb5, 0xc, 0xf2, 0xb0, 0xbb, 0x56, 0xd2, 0x42 }
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/DecodeFile/ifc_audiostream.h b/Src/Agave/DecodeFile/ifc_audiostream.h
new file mode 100644
index 00000000..586d704c
--- /dev/null
+++ b/Src/Agave/DecodeFile/ifc_audiostream.h
@@ -0,0 +1,65 @@
+#ifndef NULLSOFT_AGAVE_IFC_AUDIOSTREAM_H
+#define NULLSOFT_AGAVE_IFC_AUDIOSTREAM_H
+
+#include <bfc/dispatch.h>
+
+class ifc_audiostream : public Dispatchable
+{
+protected:
+ ifc_audiostream() {}
+ ~ifc_audiostream() {}
+public:
+ /* returns number of bytes written to buffer.
+ * a return value of 0 means EOF
+ */
+ size_t ReadAudio(void *buffer, size_t sizeBytes);
+
+ size_t ReadAudio(void *buffer, size_t, int *killswitch, int *errorCode);
+ /* Seeks to a point in the stream in milliseconds
+ * returns TRUE if successful, FALSE otherwise
+ */
+ int SeekToTimeMs(int millisecs);
+
+ /* returns 1 if this stream is seekable using SeekToTime, 0 otherwise
+ */
+ int CanSeek();
+public:
+ DISPATCH_CODES
+ {
+ IFC_AUDIOSTREAM_READAUDIO = 10,
+ IFC_AUDIOSTREAM_READAUDIO2 = 11,
+ IFC_AUDIOSTREAM_SEEKTOTIMEMS = 20,
+ IFC_AUDIOSTREAM_CANSEEK = 30,
+ };
+};
+
+inline size_t ifc_audiostream::ReadAudio(void *buffer, size_t sizeBytes)
+{
+ return _call(IFC_AUDIOSTREAM_READAUDIO, (size_t)0, buffer, sizeBytes);
+}
+
+inline size_t ifc_audiostream::ReadAudio(void *buffer, size_t sizeBytes, int *killswitch, int *errorCode)
+{
+ void *params[4] = { &buffer, &sizeBytes, &killswitch, &errorCode};
+ size_t retval;
+
+ if (_dispatch(IFC_AUDIOSTREAM_READAUDIO2, &retval, params, 4))
+ return retval;
+ else
+ {
+ *errorCode=0;
+ return ReadAudio(buffer, sizeBytes);
+ }
+}
+
+inline int ifc_audiostream::SeekToTimeMs(int millisecs)
+{
+ return _call(IFC_AUDIOSTREAM_SEEKTOTIMEMS, (int)0, millisecs);
+}
+
+inline int ifc_audiostream::CanSeek()
+{
+ return _call(IFC_AUDIOSTREAM_CANSEEK, (int)0);
+}
+
+#endif
diff --git a/Src/Agave/DecodeFile/ifc_raw_media_reader.h b/Src/Agave/DecodeFile/ifc_raw_media_reader.h
new file mode 100644
index 00000000..cc86f1a9
--- /dev/null
+++ b/Src/Agave/DecodeFile/ifc_raw_media_reader.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <bfc/dispatch.h>
+#include <bfc/error.h>
+
+class ifc_raw_media_reader : public Dispatchable
+{
+protected:
+ ifc_raw_media_reader() {}
+ ~ifc_raw_media_reader() {}
+
+public:
+ int Read(void *buffer, size_t buffer_size, size_t *bytes_read);
+ /* TODO: we'll probably need stuff in here like EndOfFile, determining a good buffer size, etc */
+
+ DISPATCH_CODES
+ {
+ RAW_READ
+ };
+};
+
+inline int ifc_raw_media_reader::Read(void *buffer, size_t buffer_size, size_t *bytes_read)
+{
+ return _call(RAW_READ, (int)NErr_NotImplemented, buffer, buffer_size, bytes_read);
+}
+
diff --git a/Src/Agave/DecodeFile/svc_raw_media_reader.h b/Src/Agave/DecodeFile/svc_raw_media_reader.h
new file mode 100644
index 00000000..c70c8085
--- /dev/null
+++ b/Src/Agave/DecodeFile/svc_raw_media_reader.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <bfc/dispatch.h>
+#include "ifc_raw_media_reader.h"
+#include <bfc/error.h>
+
+class svc_raw_media_reader : public Dispatchable
+{
+protected:
+ svc_raw_media_reader() {}
+ ~svc_raw_media_reader() {}
+public:
+ static FOURCC getServiceType() { return svc_raw_media_reader::SERVICETYPE; }
+ int CreateRawMediaReader(const wchar_t *filename, ifc_raw_media_reader **reader);
+public:
+ DISPATCH_CODES
+ {
+ CREATERAWMEDIAREADER = 0,
+ };
+
+
+ enum
+ {
+ SERVICETYPE = MK4CC('r','a','w','m')
+ };
+};
+
+inline int svc_raw_media_reader::CreateRawMediaReader(const wchar_t *filename, ifc_raw_media_reader **reader)
+{
+ return _call(CREATERAWMEDIAREADER, (int)NErr_NotImplemented, filename, reader);
+}
+
diff --git a/Src/Agave/Encode/ifc_audioFileEncoder.h b/Src/Agave/Encode/ifc_audioFileEncoder.h
new file mode 100644
index 00000000..f0f7c3ce
--- /dev/null
+++ b/Src/Agave/Encode/ifc_audioFileEncoder.h
@@ -0,0 +1,60 @@
+#pragma once
+#include <bfc/dispatch.h>
+class ifc_audioFileEncoder : public Dispatchable
+{
+protected:
+ ifc_audioFileEncoder() {}
+ ~ifc_audioFileEncoder() {}
+public:
+ /*
+ @param frame - frame number, optional (pass 0 every time if you don't have it).
+ it is used for special purposes and is not generally needed.
+ @param data - the input data (audio)
+ @param data_len - number of valid bytes in data
+ @param data_used - on return, set to the number of audio bytes read
+
+ note for implementors:
+ it is highly recommended that implementation use all available input data, but it is not required.
+
+ note for users:
+ if not all input data is read, you need to pass in the old data again
+ but have more available. This is likely to happen when the block size of the codec
+ does not match your buffer size
+ */
+ int Feed(uint32_t frame, const void *data, size_t data_len, size_t *data_used);
+
+ // same as above, but used when you have no more input to pass
+ // you can pass more audio data if you like (preferred if possible)
+ // or pass 0 for data & data_len if you passed all your data to Feed()
+ // note to implementors:
+ // for many implementations: close your encoder (e.g. vorbis) but not your file writer (e.g. ogg)
+ // note to users:
+ // you still need to call Finish().
+ int Finish(uint32_t frame, const void *data, size_t data_len, size_t *data_used);
+
+ // call this to do whatever necessary
+ // this is a separate call than Finish() because of time-constraints and the killswitch
+ // for many implementations: close your file writer object here, write seek table, etc.
+ // note to users:
+ // after this function succeeds, you may use the file (write metadata, etc)
+ int Finalize(int *killswitch);
+
+ // @param block_size - on return, set to the 'natural' number of bytes that the audio encoder expects
+ // can be helpful for users of this object to do more efficient I/O
+ // optional (check the return value when you call this!)
+ // but recommended
+ int GetBlockSize(size_t *block_size);
+
+ // @param fill_size - on return, set to the number of bytes needed to fill the audio encoder's current block
+ // might be 0 for some types (WAV).
+ // can be helpful for users of this object to do more efficient I/O
+ // optional (check the return value when you call this!)
+ // don't implement unless it's easy
+ int GetFillSize(size_t *fill_size);
+
+ // @param bytes_written - on return, set to the number of encoded bytes written so far.
+ // used by the CD ripper to show a 'real time' bitrate
+ // optional (check the return value when you call this!)
+ // don't implement unless it's easy
+ int GetBytesWritten(size_t *bytes_written);
+}; \ No newline at end of file
diff --git a/Src/Agave/Encode/notes.txt b/Src/Agave/Encode/notes.txt
new file mode 100644
index 00000000..1bd767e6
--- /dev/null
+++ b/Src/Agave/Encode/notes.txt
@@ -0,0 +1,23 @@
+notes for encoders
+
+====
+two types of encoders:
+1) File encoders. These write directly to a file.
+2) Stream encoders. These return the encoded audio data in a user-provided buffer
+
+For example, an AAC encoder could implement a file encoder for MP4/M4A files, but these aren't streamable.
+ADTS AAC however, would be streamable.
+
+====
+Two ways of feeding the data
+1) Push model. The user of the class passes data in a user-owned data buffer.
+2) Pull model. The implementor of the class pulls data from a user-provided callback (data is stored in an implementor-owned buffer)
+
+Push encoders should be used when the incoming audio data is not immediately available (live recording, CD ripping).
+Pull encoders should only be used when all the audio data is immediately available (e.g. WAV file).
+
+When in doubt, use a push encoder. Pull encoders offer a potential advantage of better memory usage (fewer memcpy's in most implementations), but a push encoder should serve all needs.
+
+====
+Note that encoders should be as non-blocking as possible (except for, obviously, computation, file I/O and thread synchronization for multi-core-aware encoders).
+It it not reommended to Sleep(), select() [network I/O], etc. Stick to what the API was designed for :)
diff --git a/Src/Agave/Encode/svc_audioFileEncoder.h b/Src/Agave/Encode/svc_audioFileEncoder.h
new file mode 100644
index 00000000..7368a23b
--- /dev/null
+++ b/Src/Agave/Encode/svc_audioFileEncoder.h
@@ -0,0 +1,64 @@
+#pragma once
+/*
+Service for creating Audio Encoders which encode straight to a file.
+
+This interface is not meant to do the encoding itself, it is a factory to create and destroy
+encoder objects (ifc_audioFileEncoder)
+*/
+#include <bfc/dispatch.h>
+#include "ifc_audioFileEncoder.h"
+#include "../DecodeFile/api_decodefile.h" // for AudioParameters struct
+#include <bfc/std_mkncc.h> // for MKnCC()
+class svc_audioFileEncoder : public Dispatchable
+{
+protected:
+ svc_audioFileEncoder() {}
+ ~svc_audioFileEncoder() {}
+public:
+ static FOURCC getServiceType() { return svc_albumArtProvider::SERVICETYPE; }
+ /*
+ General parameter notes (for all methods of this class):
+ @param profile is a filename of an INI file where the encoder settings are stored
+ @param parameters defines the input audio data. For methods where this parameter
+ is optional (default parameter value == 0), it is meant to be passed to optionally
+ limit configuration choices. For example, an AAC encoder could hide surround-sound
+ encoding options when parameters->channels == 2
+ */
+
+ // return a user-friendly name for the encoder,
+ // e.g. "Nullsoft FLAC encoder v2.1"
+ const wchar_t *GetName();
+
+ // retrieve information about a particular profile
+ // @param profile_item information to retrieve. currently, there are only three defined strings
+ // "bitrate" -- retrieve an estimate bitrate (in kbps) for the profile
+ // "profile" -- retrieve a more specific name for a given profile (and optional input parameters)
+ // e.g. an AAC encoder could return "HE-AAC v2, 16kbps, MP4 File Format" or "AAC LC, ADTS stream"
+ // "settings" -- retrieve a string that codifies the settings in the profile
+ // for most codecs, this should mirror what the commandline string would be for the corresponding
+ // commandline codec (flac.exe, lame.exe, etc).
+ // e.g. "-V 2"
+ int GetProfileInfo(const wchar_t *profile, const wchar_t *profile_item, wchar_t *value, size_t value_cch, const AudioParameters *parameters = 0);
+
+ // not currently used for anything
+ int SetProfileInfo(const wchar_t *profile, const wchar_t *profile_item, const wchar_t *value, AudioParameters *parameters = 0);
+
+ // this function gets the party started. call after you have opened your input file (thru
+ // api_decodefile, for example) so you can pass in a valid parameters struct.
+ // @param filename destination filename
+ int Create(ifc_audioFileEncoder **encoder, const wchar_t *filename, const wchar_t *profile, const AudioParameters *parameters);
+
+ // call this when you are done
+ void Destroy(ifc_audioFileEncoder *encoder);
+
+ // if parent is NULL, pop up a modal dialog/window
+ // if parent is not NULL, return a modeless child dialog/window
+ HWND Configure(HWND parent, const wchar_t *profile, const AudioParameters *parameters = 0);
+
+
+ enum
+ {
+ SERVICETYPE = MK4CC('a','f','e', 'n')
+ };
+
+}; \ No newline at end of file
diff --git a/Src/Agave/ExplorerFindFile/api_explorerfindfile.h b/Src/Agave/ExplorerFindFile/api_explorerfindfile.h
new file mode 100644
index 00000000..b9fb0411
--- /dev/null
+++ b/Src/Agave/ExplorerFindFile/api_explorerfindfile.h
@@ -0,0 +1,46 @@
+#ifndef NULLSOFT_API_EXPLORERFINDFILE_H
+#define NULLSOFT_API_EXPLORERFINDFILE_H
+
+#include <bfc/dispatch.h>
+
+class api_explorerfindfile : public Dispatchable
+{
+protected:
+ api_explorerfindfile() {}
+ ~api_explorerfindfile() {}
+public:
+ BOOL AddFile(wchar_t* file);
+ BOOL ShowFiles(void);
+ void Reset(void);
+public:
+ DISPATCH_CODES
+ {
+ API_EXPLORERFINDFILE_ADDFILE = 10,
+ API_EXPLORERFINDFILE_SHOWFILES = 11,
+ API_EXPLORERFINDFILE_RESET = 12,
+ };
+};
+
+inline BOOL api_explorerfindfile::AddFile(wchar_t* file)
+{
+ return _call(API_EXPLORERFINDFILE_ADDFILE, (BOOL)0, file);
+}
+
+inline BOOL api_explorerfindfile::ShowFiles(void)
+{
+ return _call(API_EXPLORERFINDFILE_SHOWFILES, (BOOL)0);
+}
+
+inline void api_explorerfindfile::Reset(void)
+{
+ _voidcall(API_EXPLORERFINDFILE_RESET);
+}
+
+extern api_explorerfindfile *ExplorerFindFileManager;
+#define WASABI_API_EXPLORERFINDFILE ExplorerFindFileManager
+
+// {83D6CD21-D67A-4326-A5B2-E1EFD664ADB5}
+static const GUID ExplorerFindFileApiGUID =
+{ 0x83d6cd21, 0xd67a, 0x4326, { 0xa5, 0xb2, 0xe1, 0xef, 0xd6, 0x64, 0xad, 0xb5 } };
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Language/api_language.h b/Src/Agave/Language/api_language.h
new file mode 100644
index 00000000..09354531
--- /dev/null
+++ b/Src/Agave/Language/api_language.h
@@ -0,0 +1,330 @@
+#ifndef NULLSOFT_API_LANGUAGE_H
+#define NULLSOFT_API_LANGUAGE_H
+
+#include <bfc/dispatch.h>
+#include "lang.h"
+#include <locale.h>
+
+#if (_MSC_VER <= 1200)
+ struct threadlocaleinfostruct;
+ struct threadmbcinfostruct;
+ typedef struct threadlocaleinfostruct * pthreadlocinfo;
+ typedef struct threadmbcinfostruct * pthreadmbcinfo;
+
+ typedef struct localeinfo_struct
+ {
+ pthreadlocinfo locinfo;
+ pthreadmbcinfo mbcinfo;
+ } _locale_tstruct, *_locale_t;
+#endif
+
+class api_language : public Dispatchable
+{
+protected:
+ api_language() {}
+ ~api_language() {}
+public:
+ char *GetString(HINSTANCE hinst, HINSTANCE owner, UINT uID, char *str=NULL, size_t maxlen=0);
+ wchar_t *GetStringW(HINSTANCE hinst, HINSTANCE owner, UINT uID, wchar_t *str=NULL, size_t maxlen=0);
+
+ char *GetStringFromGUID(const GUID guid, HINSTANCE owner, UINT uID, char *str=NULL, size_t maxlen=0);
+ wchar_t *GetStringFromGUIDW(const GUID guid, HINSTANCE owner, UINT uID, wchar_t *str=NULL, size_t maxlen=0);
+
+ HINSTANCE FindDllHandleByGUID(GUID guid);
+ HINSTANCE FindDllHandleByString(const char* str);
+ HINSTANCE FindDllHandleByStringW(const wchar_t* str);
+ HINSTANCE StartLanguageSupport(HINSTANCE hinstance, const GUID guid);
+
+ const wchar_t *GetLanguageFolder();
+
+ #define LANG_IDENT_STR 0
+ #define LANG_LANG_CODE 1
+ #define LANG_COUNTRY_CODE 2
+ const wchar_t *GetLanguageIdentifier(int mode);
+
+ HWND CreateLDialogParam(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param);
+ INT_PTR LDialogBoxParam(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param);
+ HMENU LoadLMenu(HINSTANCE localised, HINSTANCE original, UINT id);
+
+ HWND CreateLDialogParamW(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param);
+ INT_PTR LDialogBoxParamW(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param);
+ HMENU LoadLMenuW(HINSTANCE localised, HINSTANCE original, UINT id);
+
+ void* LoadResourceFromFileA(HINSTANCE hinst, HINSTANCE owner, LPCSTR lpType, LPCSTR lpName, DWORD* size);
+ void* LoadResourceFromFileW(HINSTANCE hinst, HINSTANCE owner, LPCWSTR lpType, LPCWSTR lpName, DWORD* size);
+
+ HACCEL LoadAcceleratorsA(HINSTANCE hinst, HINSTANCE owner, LPCSTR lpTableName);
+ HACCEL LoadAcceleratorsW(HINSTANCE hinst, HINSTANCE owner, LPCWSTR lpTableName);
+
+ // Implemented in 5.58+
+ // When called this will attempt to set the locale used for numeric representation
+ // to that of the user running the current Winamp instance as long as the language
+ // and country identifiers match those reported within the language pack (if used)
+ //
+ // If you're running under a different thread then this will need to be called as
+ // the locale is set on a per thread basis which generally means anything under the
+ // Winamp process will be handled correctly unless a UI aspect is running under a
+ // different thread. Internally this is called within winamp.exe and vis_milk2.dll
+ BOOL UseUserNumericLocale();
+
+ // Get_C_NumericLocale() is a wrapper for _create_locale(LC_NUMERIC, "C") which can
+ // then be used in _atof_l(..), _sscanf_l(..) or other locale based functions when
+ // you need to process numbers without localisation handling ie the "C" locale.
+ // This function is provided for convenience unless you want to do it all manually.
+ _locale_t Get_C_NumericLocale();
+
+ // Implemented in 5.64+
+ wchar_t* FormattedSizeString(wchar_t *out, int cchLen, __int64 size);
+
+public:
+ DISPATCH_CODES
+ {
+ API_LANGUAGE_GETSTRING = 10,
+ API_LANGUAGE_GETSTRINGW = 11,
+
+ API_LANGUAGE_GETSTRINGFROMGUID = 12,
+ API_LANGUAGE_GETSTRINGFROMGUIDW = 13,
+
+ API_LANGUAGE_GETHINSTANCEBYGUID = 20,
+ API_LANGUAGE_GETHINSTANCEBYNAME = 21,
+ API_LANGUAGE_GETHINSTANCEBYNAMEW = 22,
+
+ API_LANGUAGE_STARTUP = 30,
+ API_LANGUAGE_SHUTDOWN = 31,
+
+ API_LANGUAGE_GETLANGUAGEFOLDER = 40,
+
+ API_LANGUAGE_CREATELDIALOGPARAM = 50,
+ API_LANGUAGE_LDIALOGBOXPARAM = 51,
+ API_LANGUAGE_LOADLMENU = 52,
+ API_LANGUAGE_CREATELDIALOGPARAMW = 53,
+ API_LANGUAGE_LDIALOGBOXPARAMW = 54,
+ API_LANGUAGE_LOADLMENUW = 55,
+
+ API_LANGUAGE_GETLANGUAGEIDENTIFIER = 60,
+
+ API_LANGUAGE_LOADRESOURCEFROMFILEA = 70,
+ API_LANGUAGE_LOADRESOURCEFROMFILEW = 71,
+
+ API_LANGUAGE_LOADACCELERATORSA = 80,
+ API_LANGUAGE_LOADACCELERATORSW = 81,
+
+ // Implemented in 5.58+
+ // See UseUserNumericLocale notes
+ API_LANGUAGE_USEUSERNUMERICLOCALE = 90,
+ API_LANGUAGE_GET_C_NUMERICLOCALE = 91,
+
+ // Implemented in 5.64+
+ API_LANGUAGE_FORMATTEDSIZESTRING = 100,
+ };
+};
+
+inline char *api_language::GetString(HINSTANCE hinst, HINSTANCE owner, UINT uID, char *str, size_t maxlen)
+{
+ return _call(API_LANGUAGE_GETSTRING, (char * )0, hinst, owner, uID, str, maxlen);
+}
+
+inline wchar_t *api_language::GetStringW(HINSTANCE hinst, HINSTANCE owner, UINT uID, wchar_t *str, size_t maxlen)
+{
+ return _call(API_LANGUAGE_GETSTRINGW, (wchar_t * )0, hinst, owner, uID, str, maxlen);
+}
+
+inline char *api_language::GetStringFromGUID(const GUID guid, HINSTANCE owner, UINT uID, char *str, size_t maxlen)
+{
+ return _call(API_LANGUAGE_GETSTRINGFROMGUID, (char * )0, guid, owner, uID, str, maxlen);
+}
+
+inline wchar_t *api_language::GetStringFromGUIDW(const GUID guid, HINSTANCE owner, UINT uID, wchar_t *str, size_t maxlen)
+{
+ return _call(API_LANGUAGE_GETSTRINGFROMGUIDW, (wchar_t * )0, guid, owner, uID, str, maxlen);
+}
+
+inline HINSTANCE api_language::FindDllHandleByGUID(const GUID guid)
+{
+ return _call(API_LANGUAGE_GETHINSTANCEBYGUID, (HINSTANCE )0, guid);
+}
+
+inline HINSTANCE api_language::FindDllHandleByString(const char* str)
+{
+ return _call(API_LANGUAGE_GETHINSTANCEBYNAME, (HINSTANCE )0, str);
+}
+
+inline HINSTANCE api_language::FindDllHandleByStringW(const wchar_t* str)
+{
+ return _call(API_LANGUAGE_GETHINSTANCEBYNAMEW, (HINSTANCE )0, str);
+}
+
+inline HINSTANCE api_language::StartLanguageSupport(HINSTANCE hinstance, const GUID guid)
+{
+ return _call(API_LANGUAGE_STARTUP, (HINSTANCE )0, hinstance, guid);
+}
+
+inline const wchar_t *api_language::GetLanguageFolder()
+{
+ return _call(API_LANGUAGE_GETLANGUAGEFOLDER, (const wchar_t *)0);
+}
+
+inline HWND api_language::CreateLDialogParam(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param)
+{
+ return _call(API_LANGUAGE_CREATELDIALOGPARAM, (HWND)0, localised, original, id, parent, proc, param);
+}
+
+inline INT_PTR api_language::LDialogBoxParam(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param)
+{
+ return _call(API_LANGUAGE_LDIALOGBOXPARAM, (INT_PTR)0, localised, original, id, parent, proc, param);
+}
+
+inline HMENU api_language::LoadLMenu(HINSTANCE localised, HINSTANCE original, UINT id)
+{
+ return _call(API_LANGUAGE_LOADLMENU, (HMENU)0, localised, original, id);
+}
+
+inline HWND api_language::CreateLDialogParamW(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param)
+{
+ return _call(API_LANGUAGE_CREATELDIALOGPARAMW, (HWND)0, localised, original, id, parent, proc, param);
+}
+
+inline INT_PTR api_language::LDialogBoxParamW(HINSTANCE localised, HINSTANCE original, UINT id, HWND parent, DLGPROC proc, LPARAM param)
+{
+ return _call(API_LANGUAGE_LDIALOGBOXPARAMW, (INT_PTR)0, localised, original, id, parent, proc, param);
+}
+
+inline HMENU api_language::LoadLMenuW(HINSTANCE localised, HINSTANCE original, UINT id)
+{
+ return _call(API_LANGUAGE_LOADLMENUW, (HMENU)0, localised, original, id);
+}
+
+inline const wchar_t *api_language::GetLanguageIdentifier(int mode)
+{
+ return _call(API_LANGUAGE_GETLANGUAGEIDENTIFIER, (const wchar_t *)0, mode);
+}
+
+inline void *api_language::LoadResourceFromFileA(HINSTANCE hinst, HINSTANCE owner, LPCSTR lpType, LPCSTR lpName, DWORD* size)
+{
+ return _call(API_LANGUAGE_LOADRESOURCEFROMFILEA, (void*)0, hinst, owner, lpType, lpName, size);
+}
+
+inline void *api_language::LoadResourceFromFileW(HINSTANCE hinst, HINSTANCE owner, LPCWSTR lpType, LPCWSTR lpName, DWORD* size)
+{
+ return _call(API_LANGUAGE_LOADRESOURCEFROMFILEW, (void*)0, hinst, owner, lpType, lpName, size);
+}
+
+inline HACCEL api_language::LoadAcceleratorsA(HINSTANCE hinst, HINSTANCE owner, LPCSTR lpTableName)
+{
+ return _call(API_LANGUAGE_LOADACCELERATORSA, (HACCEL)NULL, hinst, owner, lpTableName);
+}
+
+inline HACCEL api_language::LoadAcceleratorsW(HINSTANCE hinst, HINSTANCE owner, LPCWSTR lpTableName)
+{
+ return _call(API_LANGUAGE_LOADACCELERATORSA, (HACCEL)NULL, hinst, owner, lpTableName);
+}
+
+inline BOOL api_language::UseUserNumericLocale()
+{
+ return _call(API_LANGUAGE_USEUSERNUMERICLOCALE, (BOOL)0);
+}
+
+inline _locale_t api_language::Get_C_NumericLocale()
+{
+ return _call(API_LANGUAGE_GET_C_NUMERICLOCALE, (_locale_t)0);
+}
+
+inline wchar_t *api_language::FormattedSizeString(wchar_t *out, int cchLen, __int64 size)
+{
+ return _call(API_LANGUAGE_FORMATTEDSIZESTRING, (wchar_t*)0, out, cchLen, size);
+}
+
+
+// utility macros and relevant predefined variables for use with the service + macros
+extern api_language *languageManager;
+#define WASABI_API_LNG languageManager
+
+extern HINSTANCE api_localised_hinstance;
+#define WASABI_API_LNG_HINST api_localised_hinstance
+
+extern HINSTANCE api_orig_hinstance;
+#define WASABI_API_ORIG_HINST api_orig_hinstance
+#define WASABI_API_LNGSTR WASABI_API_LNG->GetString
+//#ifdef UNICODE
+//#define WASABI_API_LNGSTR WASABI_API_LNG->GetStringW
+//#else
+//#define WASABI_API_LNGSTR WASABI_API_LNG->GetStringA
+//#endif
+// use this is you want a temp copy of the string
+#define WASABI_API_LNGSTRING(uID) \
+ WASABI_API_LNGSTR(WASABI_API_LNG_HINST,WASABI_API_ORIG_HINST,uID)
+// use this is you want a temp copy of the string but need it to fallback to a different module
+#define WASABI_API_LNGSTRING_HINST(hinst,uID) \
+ WASABI_API_LNGSTR(WASABI_API_LNG_HINST,hinst,uID)
+// use this is you want a copy of the string
+#define WASABI_API_LNGSTRING_BUF(uID,buf,len) \
+ WASABI_API_LNGSTR(WASABI_API_LNG_HINST,WASABI_API_ORIG_HINST,uID,buf,len)
+// use this is you want a copy of the string but need it to fallback to a different module
+#define WASABI_API_LNGSTRING_HINST_BUF(hinst,uID,buf,len) \
+ WASABI_API_LNGSTR(WASABI_API_LNG_HINST,hinst,uID,buf,len)
+
+// unicode versions of the above macros
+#define WASABI_API_LNGSTRW WASABI_API_LNG->GetStringW
+#define WASABI_API_LNGSTRINGW(uID) \
+ WASABI_API_LNGSTRW(WASABI_API_LNG_HINST,WASABI_API_ORIG_HINST,uID)
+#define WASABI_API_LNGSTRINGW_HINST(hinst,uID) \
+ WASABI_API_LNGSTRW(WASABI_API_LNG_HINST,hinst,uID)
+#define WASABI_API_LNGSTRINGW_BUF(uID,buf,len) \
+ WASABI_API_LNGSTRW(WASABI_API_LNG_HINST,WASABI_API_ORIG_HINST,uID,buf,len)
+#define WASABI_API_LNGSTRINGW_BUF_HINST(hinst,uID,buf,len) \
+ WASABI_API_LNGSTRW(WASABI_API_LNG_HINST,hinst,uID,buf,len)
+
+// Dialog handling functions (will revert back to the non-localised version if not valid/present)
+#define WASABI_API_CREATEDIALOGPARAM(id, parent, proc, param) \
+ WASABI_API_LNG->CreateLDialogParam(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, param)
+#define WASABI_API_CREATEDIALOG(id, parent, proc) \
+ WASABI_API_LNG->CreateLDialogParam(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, 0)
+
+#define WASABI_API_CREATEDIALOGPARAMW(id, parent, proc, param) \
+ WASABI_API_LNG->CreateLDialogParamW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, param)
+#define WASABI_API_CREATEDIALOGW(id, parent, proc) \
+ WASABI_API_LNG->CreateLDialogParamW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, 0)
+
+#define WASABI_API_DIALOGBOXPARAM(id, parent, proc, param) \
+ WASABI_API_LNG->LDialogBoxParam(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, param)
+#define WASABI_API_DIALOGBOX(id, parent, proc) \
+ WASABI_API_LNG->LDialogBoxParam(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, 0)
+
+#define WASABI_API_DIALOGBOXPARAMW(id, parent, proc, param) \
+ WASABI_API_LNG->LDialogBoxParamW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, param)
+#define WASABI_API_DIALOGBOXW(id, parent, proc) \
+ WASABI_API_LNG->LDialogBoxParamW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id, parent, (DLGPROC)proc, 0)
+
+#define WASABI_API_LOADMENU(id) \
+ WASABI_API_LNG->LoadLMenu(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id)
+#define WASABI_API_LOADMENUW(id) \
+ WASABI_API_LNG->LoadLMenuW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, id)
+
+
+#define WASABI_API_LOADACCELERATORSA(__id) \
+ WASABI_API_LNG->LoadAcceleratorsA(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, MAKEINTRESOURCEA(__id))
+#define WASABI_API_LOADACCELERATORSW(__id) \
+ WASABI_API_LNG->LoadAcceleratorsW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, MAKEINTRESOURCEW(__id))
+
+#ifdef UNICODE
+#define WASABI_API_LOADACCELERATORS WASABI_API_LOADACCELERATORSW
+#else
+#define WASABI_API_LOADACCELERATORS WASABI_API_LOADACCELERATORSA
+#endif
+
+#define WASABI_API_START_LANG(orig_hinst, guid) \
+{ \
+ WASABI_API_ORIG_HINST = orig_hinst; \
+ WASABI_API_LNG_HINST = WASABI_API_LNG->StartLanguageSupport(WASABI_API_ORIG_HINST,guid); \
+}
+
+#define WASABI_API_LOADRESFROMFILEA(lpType, lpName, size) \
+ WASABI_API_LNG->LoadResourceFromFileA(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, lpType, lpName, size)
+#define WASABI_API_LOADRESFROMFILEW(lpType, lpName, size) \
+ WASABI_API_LNG->LoadResourceFromFileW(WASABI_API_LNG_HINST, WASABI_API_ORIG_HINST, lpType, lpName, size)
+
+// {30AED4E5-EF10-4277-8D49-27AB5570E891}
+static const GUID languageApiGUID =
+{ 0x30aed4e5, 0xef10, 0x4277, { 0x8d, 0x49, 0x27, 0xab, 0x55, 0x70, 0xe8, 0x91 } };
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Language/lang.h b/Src/Agave/Language/lang.h
new file mode 100644
index 00000000..03595a1b
--- /dev/null
+++ b/Src/Agave/Language/lang.h
@@ -0,0 +1,643 @@
+#ifndef _LANG_GUIDS_H_
+#define _LANG_GUIDS_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// this is just the stringtable id and the
+// stringtable block where the guid is stored
+#define LANG_DLL_GUID_STRING_ID 65535
+#define LANG_DLL_GUID_BLOCK_ID 4096
+
+// this is the stringtable id in winamp.exe's lng file where
+// the language of the lang pack is declared.
+// the actual string is defined as language_code-country_code
+// e.g.
+// en-US - US English
+// en-GB - UK English
+#define LANG_PACK_LANG_ID 65534
+
+// this is the indentifiers required as of 5.57+ for the localisation
+// 'about page' shown in supporting language packs in the 'about' box
+#define LANG_DLL_AUTHOR_HOMEPAGE 65533
+#define LANG_DLL_AUTHOR_HOMEPAGE2 65532
+#define LANG_DLL_LOCALIZED_HOMEPAGE 65531
+#define LANG_DLL_ABOUT_TRANSLATION_DLG_ID 1378
+
+// this holds all of the guids that will be used in modules lng files
+// using these will allow you to make use of the language resources
+// between plugins / for 3rd party plugins for compatability support
+
+// {A0099AA7-F980-45cf-818D-64EAA9F4EF4B}
+static const GUID WinampLangGUID =
+{ 0xa0099aa7, 0xf980, 0x45cf, { 0x81, 0x8d, 0x64, 0xea, 0xa9, 0xf4, 0xef, 0x4b } };
+
+// {0E844B2A-70E8-4007-A73A-E9C05DB3F06D}
+static const GUID WinampALangGUID =
+{ 0xe844b2a, 0x70e8, 0x4007, { 0xa7, 0x3a, 0xe9, 0xc0, 0x5d, 0xb3, 0xf0, 0x6d } };
+
+// {250FAA3C-20CD-49db-A932-67B1C0191B0E}
+static const GUID GenHotkeysLangGUID =
+{ 0x250faa3c, 0x20cd, 0x49db, { 0xa9, 0x32, 0x67, 0xb1, 0xc0, 0x19, 0x1b, 0xe } };
+
+// {25B50046-5B31-418b-B77E-1B0D140D64ED}
+static const GUID GenTrayLangGUID =
+{ 0x25b50046, 0x5b31, 0x418b, { 0xb7, 0x7e, 0x1b, 0xd, 0x14, 0xd, 0x64, 0xed } };
+
+// {3D968813-F245-40ad-8589-5599C754B924}
+static const GUID GenMlLangGUID =
+{ 0x3d968813, 0xf245, 0x40ad, { 0x85, 0x89, 0x55, 0x99, 0xc7, 0x54, 0xb9, 0x24 } };
+
+// {A3A1E7C0-761B-4391-A08A-F0D7AF38931C}
+static const GUID MlBookmarkLangGUID =
+{ 0xa3a1e7c0, 0x761b, 0x4391, { 0xa0, 0x8a, 0xf0, 0xd7, 0xaf, 0x38, 0x93, 0x1c } };
+
+// {C1DE900F-8047-4B04-AE6B-8EACD9A9B8E1}
+static const GUID MlNFTLangGUID =
+{ 0xc1de900f, 0x8047, 0x4b04, { 0xae, 0x6b, 0x8e, 0xac, 0xd9, 0xa9, 0xb8, 0xe1 } };
+
+// {DBF92DD3-766E-42E8-A4D2-AE1AC88CF2D1}
+static const GUID MlFanZoneLangGUID =
+{ 0xdbf92dd3, 0x766e, 0x42e8, { 0xa4, 0xd2, 0xae, 0x1a, 0xc8, 0x8c, 0xf2, 0xd1 } };
+
+// // {4959A8EF-B760-4C33-B18C-715EF018B365}
+static const GUID MlHotmixRadioLangGUID =
+{ 0x4959a8ef, 0xb760, 0x4c33, { 0xb1, 0x8c, 0x71, 0x5e, 0xf0, 0x18, 0xb3, 0x65 } };
+
+// {40450D34-E85A-428c-A01C-B2546BF23CE0}
+static const GUID MlDashboardLangGUID =
+{ 0x40450d34, 0xe85a, 0x428c, { 0xa0, 0x1c, 0xb2, 0x54, 0x6b, 0xf2, 0x3c, 0xe0 } };
+
+// {168BA411-7E26-4749-98F0-FF02810D9B51}
+static const GUID MlADDONSLangGUID =
+{ 0x168ba411, 0x7e26, 0x4749, { 0x98, 0xf0, 0xff, 0x2, 0x81, 0xd, 0x9b, 0x51 } };
+
+// {7F31F590-6602-45c9-B3F8-F61AE05BD1D3}
+static const GUID MlNowPlayingLangGUID =
+{ 0x7f31f590, 0x6602, 0x45c9, { 0xb3, 0xf8, 0xf6, 0x1a, 0xe0, 0x5b, 0xd1, 0xd3 } };
+
+// {F8756C00-11D2-4857-8C50-163AE4A57783}
+static const GUID MlHistoryLangGUID =
+{ 0xf8756c00, 0x11d2, 0x4857, { 0x8c, 0x50, 0x16, 0x3a, 0xe4, 0xa5, 0x77, 0x83 } };
+
+// {5E766B4F-818E-4f14-9C42-0902B2C571DC}
+static const GUID MlPlaylistsLangGUID =
+{ 0x5e766b4f, 0x818e, 0x4f14, { 0x9c, 0x42, 0x9, 0x2, 0xb2, 0xc5, 0x71, 0xdc } };
+
+// {D006C700-557E-43c7-A580-B4C50C56957A}
+static const GUID MlOnlineLangGUID =
+{ 0xd006c700, 0x557e, 0x43c7, { 0xa5, 0x80, 0xb4, 0xc5, 0xc, 0x56, 0x95, 0x7a } };
+
+// {5F633543-148D-48cc-B683-DA82F592CF28}
+static const GUID MlReplayGainLangGUID =
+{ 0x5f633543, 0x148d, 0x48cc, { 0xb6, 0x83, 0xda, 0x82, 0xf5, 0x92, 0xcf, 0x28 } };
+
+// {699B8BA5-B292-4aba-8047-D46B0DF4E1D6}
+static const GUID MlTranscodeLangGUID =
+{ 0x699b8ba5, 0xb292, 0x4aba, { 0x80, 0x47, 0xd4, 0x6b, 0xd, 0xf4, 0xe1, 0xd6 } };
+
+// {34DF1A2D-7EAD-41ab-B1A7-9AFA6DE2AFF1}
+static const GUID EncWavLangGUID =
+{ 0x34df1a2d, 0x7ead, 0x41ab, { 0xb1, 0xa7, 0x9a, 0xfa, 0x6d, 0xe2, 0xaf, 0xf1 } };
+
+// {33BC12FD-E7F7-42ec-8FE3-2D8BD3A977C2}
+static const GUID EncWMALangGUID =
+{ 0x33bc12fd, 0xe7f7, 0x42ec, { 0x8f, 0xe3, 0x2d, 0x8b, 0xd3, 0xa9, 0x77, 0xc2 } };
+
+// {8FBADBBB-B4D5-47d9-A723-5C8C8E88EE73}
+static const GUID EncAACLangGUID =
+{ 0x8fbadbbb, 0xb4d5, 0x47d9, { 0xa7, 0x23, 0x5c, 0x8c, 0x8e, 0x88, 0xee, 0x73 } };
+
+// {F1534ECA-6E64-42c2-9781-812E61154515}
+static const GUID EncLameLangGUID =
+{ 0xf1534eca, 0x6e64, 0x42c2, { 0x97, 0x81, 0x81, 0x2e, 0x61, 0x15, 0x45, 0x15 } };
+
+// deprecated enc_flac.dll based on FLAKE
+// {5C0BA1EE-5A59-47cc-BC28-5B9F0C5EA1B7}
+static const GUID EncFlakeLangGUID =
+{ 0x5c0ba1ee, 0x5a59, 0x47cc, { 0xbc, 0x28, 0x5b, 0x9f, 0xc, 0x5e, 0xa1, 0xb7 } };
+
+// {A23C2B70-C66B-475e-8A67-E0F33FD5BD12}
+static const GUID EncVorbisLangGUID =
+{ 0xa23c2b70, 0xc66b, 0x475e, { 0x8a, 0x67, 0xe0, 0xf3, 0x3f, 0xd5, 0xbd, 0x12 } };
+
+// {D40620FB-E44B-47b3-98EE-8E5A089C0C94}
+static const GUID tagzLangGUID =
+{ 0xd40620fb, 0xe44b, 0x47b3, { 0x98, 0xee, 0x8e, 0x5a, 0x8, 0x9c, 0xc, 0x94 } };
+
+// {06A3F81D-043D-4b5c-B341-590ED7053492}
+static const GUID MlLocalLangGUID =
+{ 0x6a3f81d, 0x43d, 0x4b5c, { 0xb3, 0x41, 0x59, 0xe, 0xd7, 0x5, 0x34, 0x92 } };
+
+// {706549D3-D813-45dd-9A0B-E3793A1B63A8}
+static const GUID MlDownloadsLangGUID =
+{ 0x706549d3, 0xd813, 0x45dd, { 0x9a, 0xb, 0xe3, 0x79, 0x3a, 0x1b, 0x63, 0xa8 } };
+
+// {1FF327B2-A41D-4c67-A58A-EB09BA1470D3}
+static const GUID MlWireLangGUID =
+{ 0x1ff327b2, 0xa41d, 0x4c67, { 0xa5, 0x8a, 0xeb, 0x9, 0xba, 0x14, 0x70, 0xd3 } };
+
+// {04C986EE-9CE3-4369-820D-A64394C63D60}
+static const GUID MlPMPLangGUID =
+{ 0x4c986ee, 0x9ce3, 0x4369, { 0x82, 0xd, 0xa6, 0x43, 0x94, 0xc6, 0x3d, 0x60 } };
+
+// {E553C1A4-5DE2-4838-8000-FDF8DC377DD4}
+static const GUID PmpUSBLangGUID =
+{ 0xe553c1a4, 0x5de2, 0x4838, { 0x80, 0x0, 0xfd, 0xf8, 0xdc, 0x37, 0x7d, 0xd4 } };
+
+// {01C3E74C-261E-45e2-AA30-ED4039DCD3A2}
+static const GUID PmpP4SLangGUID =
+{ 0x1c3e74c, 0x261e, 0x45e2, { 0xaa, 0x30, 0xed, 0x40, 0x39, 0xdc, 0xd3, 0xa2 } };
+
+// {4F5B2300-19D1-4390-BE04-89019441100B}
+static const GUID PmpNJBLangGUID =
+{ 0x4f5b2300, 0x19d1, 0x4390, { 0xbe, 0x4, 0x89, 0x1, 0x94, 0x41, 0x10, 0xb } };
+
+// {B81F32B8-4AA4-4eba-8798-95F13812F638}
+static const GUID PmpACTIVESYNCLangGUID =
+{ 0xb81f32b8, 0x4aa4, 0x4eba, { 0x87, 0x98, 0x95, 0xf1, 0x38, 0x12, 0xf6, 0x38 } };
+
+// {C2EE3DA5-B29B-42a0-AB5E-B202393435D6}
+static const GUID PmpIPODLangGUID =
+{ 0xc2ee3da5, 0xb29b, 0x42a0, { 0xab, 0x5e, 0xb2, 0x2, 0x39, 0x34, 0x35, 0xd6 } };
+
+// {2C913A2F-CD49-40a1-8F1A-8EF7C2A22229}
+static const GUID MlDiscLangGUID =
+{ 0x2c913a2f, 0xcd49, 0x40a1, { 0x8f, 0x1a, 0x8e, 0xf7, 0xc2, 0xa2, 0x22, 0x29 } };
+
+// {1A710E67-5180-49ac-8102-105856ED0A2F}
+static const GUID OutDiskLangGUID =
+{ 0x1a710e67, 0x5180, 0x49ac, { 0x81, 0x2, 0x10, 0x58, 0x56, 0xed, 0xa, 0x2f } };
+
+// {858FBF71-9878-4d86-BFDD-8FEA8361238C}
+static const GUID VisNFSFLangGUID =
+{ 0x858fbf71, 0x9878, 0x4d86, { 0xbf, 0xdd, 0x8f, 0xea, 0x83, 0x61, 0x23, 0x8c } };
+
+// {BE608673-B723-4a59-9EBA-52DC77109E10}
+static const GUID VisAVSLangGUID =
+{ 0xbe608673, 0xb723, 0x4a59, { 0x9e, 0xba, 0x52, 0xdc, 0x77, 0x10, 0x9e, 0x10 } };
+
+// {226275F6-3318-4d4b-A6B3-5B1B5B077BE8}
+static const GUID VisMilkdropLangGUID =
+{ 0x226275f6, 0x3318, 0x4d4b, { 0xa6, 0xb3, 0x5b, 0x1b, 0x5b, 0x7, 0x7b, 0xe8 } };
+
+// {C5D175F1-E4E4-47ee-B85C-4EDC6B026A35}
+static const GUID VisMilk2LangGUID =
+{ 0xc5d175f1, 0xe4e4, 0x47ee, { 0xb8, 0x5c, 0x4e, 0xdc, 0x6b, 0x2, 0x6a, 0x35 } };
+
+// {87DCEEC2-1EC3-4c59-BED4-E8F42232C7D8}
+static const GUID InCDDALangGUID =
+{ 0x87dceec2, 0x1ec3, 0x4c59, { 0xbe, 0xd4, 0xe8, 0xf4, 0x22, 0x32, 0xc7, 0xd8 } };
+
+// {20395FD0-AC67-446d-B8D0-D88BFD3174FC}
+static const GUID IndshowLangGUID =
+{ 0x20395fd0, 0xac67, 0x446d, { 0xb8, 0xd0, 0xd8, 0x8b, 0xfd, 0x31, 0x74, 0xfc } };
+
+// {9475116B-F8C4-4dff-BC19-9601B238557D}
+static const GUID InFlacLangGUID =
+{ 0x9475116b, 0xf8c4, 0x4dff, { 0xbc, 0x19, 0x96, 0x1, 0xb2, 0x38, 0x55, 0x7d } };
+
+// {EA1C197A-D227-474c-A9FD-1C79DE722BDD}
+static const GUID InLineInLangGUID =
+{ 0xea1c197a, 0xd227, 0x474c, { 0xa9, 0xfd, 0x1c, 0x79, 0xde, 0x72, 0x2b, 0xdd } };
+
+// {96374982-0142-41a5-AEDE-244505C45D30}
+static const GUID InWavLangGUID =
+{ 0x96374982, 0x142, 0x41a5, { 0xae, 0xde, 0x24, 0x45, 0x5, 0xc4, 0x5d, 0x30 } };
+
+// {5C5BCA4E-279E-4867-8E24-58C8B186959A}
+static const GUID InVorbisLangGUID =
+{ 0x5c5bca4e, 0x279e, 0x4867, { 0x8e, 0x24, 0x58, 0xc8, 0xb1, 0x86, 0x95, 0x9a } };
+
+// {A786C0B0-69DE-49e2-9461-4F592808B0B3}
+static const GUID ndeLangGUID =
+{ 0xa786c0b0, 0x69de, 0x49e2, { 0x94, 0x61, 0x4f, 0x59, 0x28, 0x8, 0xb0, 0xb3 } };
+
+// {11B847DB-29A7-47ac-B386-43B40385B817}
+static const GUID InNSVLangGUID =
+{ 0x11b847db, 0x29a7, 0x47ac, { 0xb3, 0x86, 0x43, 0xb4, 0x3, 0x85, 0xb8, 0x17 } };
+
+// {5F24DF00-C163-4eaa-AB9D-22F106588C25}
+static const GUID MLOrbLangGUID =
+{ 0x5f24df00, 0xc163, 0x4eaa, { 0xab, 0x9d, 0x22, 0xf1, 0x6, 0x58, 0x8c, 0x25 } };
+
+// {0FED0FEE-C995-4499-AB47-E2482336C046}
+static const GUID InMidiLangGUID =
+{ 0xfed0fee, 0xc995, 0x4499, { 0xab, 0x47, 0xe2, 0x48, 0x23, 0x36, 0xc0, 0x46 } };
+
+// {F30C75C1-D284-4cd5-9CED-2BD9E7869438}
+static const GUID InMp4LangGUID =
+{ 0xf30c75c1, 0xd284, 0x4cd5, { 0x9c, 0xed, 0x2b, 0xd9, 0xe7, 0x86, 0x94, 0x38 } };
+
+// {CD3EEF98-011C-4213-BC16-3F91C937B9B8}
+static const GUID InMp3LangGUID =
+{ 0xcd3eef98, 0x11c, 0x4213, { 0xbc, 0x16, 0x3f, 0x91, 0xc9, 0x37, 0xb9, 0xb8 } };
+
+// {A1A39D49-671A-4c2f-AE42-BEA134EAF6A9}
+static const GUID InModLangGUID =
+{ 0xa1a39d49, 0x671a, 0x4c2f, { 0xae, 0x42, 0xbe, 0xa1, 0x34, 0xea, 0xf6, 0xa9 } };
+
+// {4B567AEB-89CE-4881-9D7D-B31D7B65979A}
+static const GUID DspSpsLangGUID =
+{ 0x4b567aeb, 0x89ce, 0x4881, { 0x9d, 0x7d, 0xb3, 0x1d, 0x7b, 0x65, 0x97, 0x9a } };
+
+// {004A91D9-CCD6-44e5-973A-4B7045C4662B}
+static const GUID OutWaveLangGUID =
+{ 0x4a91d9, 0xccd6, 0x44e5, { 0x97, 0x3a, 0x4b, 0x70, 0x45, 0xc4, 0x66, 0x2b } };
+
+// {A812F3D3-633B-4af6-8749-3BA75290BAC0}
+static const GUID OutDSLangGUID =
+{ 0xa812f3d3, 0x633b, 0x4af6, { 0x87, 0x49, 0x3b, 0xa7, 0x52, 0x90, 0xba, 0xc0 } };
+
+// {C5B78F09-3222-4a64-AA98-F1ABC5A9E355}
+static const GUID InWmLangGUID =
+{ 0xc5b78f09, 0x3222, 0x4a64, { 0xaa, 0x98, 0xf1, 0xab, 0xc5, 0xa9, 0xe3, 0x55 } };
+
+// {C14FAE1D-B410-459f-B008-1A8BE3633000}
+static const GUID burnlibLangGUID =
+{ 0xc14fae1d, 0xb410, 0x459f, { 0xb0, 0x8, 0x1a, 0x8b, 0xe3, 0x63, 0x30, 0x0 } };
+
+// {ACD05A75-030B-4943-A100-540DAD98FB00}
+static const GUID GenFFLangGUID =
+{ 0xacd05a75, 0x30b, 0x4943, { 0xa1, 0x0, 0x54, 0xd, 0xad, 0x98, 0xfb, 0x0 } };
+
+// {0CE0174D-8334-479e-B322-9D80D48FC74D}
+static const GUID MlPlgLangGUID =
+{ 0xce0174d, 0x8334, 0x479e, { 0xb3, 0x22, 0x9d, 0x80, 0xd4, 0x8f, 0xc7, 0x4d } };
+
+// {9E398E5F-EDEC-4dd8-A40D-E29B385A88C0}
+static const GUID playlistLangGUID =
+{ 0x9e398e5f, 0xedec, 0x4dd8, { 0xa4, 0xd, 0xe2, 0x9b, 0x38, 0x5a, 0x88, 0xc0 } };
+
+// {092A97EF-7DC0-41a7-80D1-90DEEB18F12D}
+static const GUID GenCrasherLangGUID =
+{ 0x92a97ef, 0x7dc0, 0x41a7, { 0x80, 0xd1, 0x90, 0xde, 0xeb, 0x18, 0xf1, 0x2d } };
+
+// {D8DBA660-90BD-431d-8F4E-189D6ACB407E}
+static const GUID MlAutoTagLangGUID =
+{ 0xd8dba660, 0x90bd, 0x431d, { 0x8f, 0x4e, 0x18, 0x9d, 0x6a, 0xcb, 0x40, 0x7e } };
+
+// {EC959D43-9122-4807-B928-7B46207AFA49}
+static const GUID InFlvLangGUID =
+{ 0xec959d43, 0x9122, 0x4807, { 0xb9, 0x28, 0x7b, 0x46, 0x20, 0x7a, 0xfa, 0x49 } };
+
+// {2430A7AC-317D-4d64-B33C-E1452A6384A2}
+static const GUID InSwfLangGUID =
+{ 0x2430a7ac, 0x317d, 0x4d64, { 0xb3, 0x3c, 0xe1, 0x45, 0x2a, 0x63, 0x84, 0xa2 } };
+
+// {22661553-8D22-4012-8D3B-0FF8FE57A9ED}
+static const GUID MlImpexLangGUID =
+{ 0x22661553, 0x8d22, 0x4012, { 0x8d, 0x3b, 0xf, 0xf8, 0xfe, 0x57, 0xa9, 0xed } };
+
+// {73760073-560C-433b-BC59-3FCC94CDEA4A}
+static const GUID EncFlacLangGUID =
+{ 0x73760073, 0x560c, 0x433b, { 0xbc, 0x59, 0x3f, 0xcc, 0x94, 0xcd, 0xea, 0x4a } };
+
+// {95C65BA3-3C34-40ec-AE74-8D2C60AAE3C8}
+static const GUID authLangGUID =
+{ 0x95c65ba3, 0x3c34, 0x40ec, { 0xae, 0x74, 0x8d, 0x2c, 0x60, 0xaa, 0xe3, 0xc8 } };
+
+// {CA36E14A-3742-4edc-A40F-2BC87F26B347}
+static const GUID InAviLangGUID =
+{ 0xca36e14a, 0x3742, 0x4edc, { 0xa4, 0xf, 0x2b, 0xc8, 0x7f, 0x26, 0xb3, 0x47 } };
+
+// {5BDA8055-292D-4fcd-8404-884C2A34A8F9}
+static const GUID InMkvLangGUID =
+{ 0x5bda8055, 0x292d, 0x4fcd, { 0x84, 0x4, 0x88, 0x4c, 0x2a, 0x34, 0xa8, 0xf9 } };
+
+// {0233DC7B-7060-43e5-8354-D2F2C7C7611D}
+static const GUID GenMudLangGUID =
+{ 0x233dc7b, 0x7060, 0x43e5, { 0x83, 0x54, 0xd2, 0xf2, 0xc7, 0xc7, 0x61, 0x1d } };
+
+// {DCCF5A41-D16B-452b-8B7A-CFCA3360D8E8}
+static const GUID omBrowserLangGUID =
+{ 0xdccf5a41, 0xd16b, 0x452b, { 0x8b, 0x7a, 0xcf, 0xca, 0x33, 0x60, 0xd8, 0xe8 } };
+
+// Winamp Android plugin (pmp_android.dll)
+// {EBFF6E00-39D8-45e6-B3EC-E3B07A45E6B0}
+static const GUID PmpAndroidLangGUID =
+{ 0xebff6e00, 0x39d8, 0x45e6, { 0xb3, 0xec, 0xe3, 0xb0, 0x7a, 0x45, 0xe6, 0xb0 } };
+
+// Winamp Wifi plugin (pmp_wifi.dll)
+// {3066887B-CA40-4683-897F-4416FE349D7E}
+static const GUID PmpWifiLangGUID =
+{ 0x3066887b, 0xca40, 0x4683, { 0x89, 0x7f, 0x44, 0x16, 0xfe, 0x34, 0x9d, 0x7e } };
+
+// Fraunhofer AAC Encoder plugin (enc_fhgaac.dll)
+// {E1763EF4-08AD-44a3-914A-8302748AB975}
+static const GUID EncFhgAacLangGUID =
+{ 0xe1763ef4, 0x8ad, 0x44a3, { 0x91, 0x4a, 0x83, 0x2, 0x74, 0x8a, 0xb9, 0x75 } };
+
+// Nullsoft Ogg Demuxer (in_ogg.dll)
+// {90B01366-39C1-47b2-99DC-BBAE2D4DC5BF}
+static const GUID InOggLangGUID =
+{ 0x90b01366, 0x39c1, 0x47b2, { 0x99, 0xdc, 0xbb, 0xae, 0x2d, 0x4d, 0xc5, 0xbf } };
+
+// Winamp Cloud plugin (ml_cloud.dll)
+// {0253CD84-4BB1-415b-B95B-B13EBD7EA6FD}
+static const GUID MlCloudLangGUID =
+{ 0x253cd84, 0x4bb1, 0x415b, { 0xb9, 0x5b, 0xb1, 0x3e, 0xbd, 0x7e, 0xa6, 0xfd } };
+
+// Winamp Cloud Device plugin (pmp_cloud.dll)
+// {5F99429F-43B0-4544-ABA0-DE5D9DA65283}
+static const GUID PmpCloudLangGUID =
+{ 0x5f99429f, 0x43b0, 0x4544, { 0xab, 0xa0, 0xde, 0x5d, 0x9d, 0xa6, 0x52, 0x83 } };
+
+// {CA4D071B-4E9B-44fd-862A-783FC763B63D}
+static const GUID MlDevicesLangGUID =
+{ 0xca4d071b, 0x4e9b, 0x44fd, { 0x86, 0x2a, 0x78, 0x3f, 0xc7, 0x63, 0xb6, 0x3d } };
+
+// {B5691276-95DB-4b5c-BA73-B904A38EFFBF}
+static const GUID InModMPTLangGUID =
+{ 0xb5691276, 0x95db, 0x4b5c, { 0xba, 0x73, 0xb9, 0x4, 0xa3, 0x8e, 0xff, 0xbf } };
+
+// {CA8AD152-9760-4AA3-AC54-7464279C5D63}
+static const GUID OutWasapiLangGUID =
+{ 0xca8ad152, 0x9760, 0x4aa3, { 0xac, 0x54, 0x74, 0x64, 0x27, 0x9c, 0x5d, 0x63 } };
+
+
+/*
+** These are guids for known 3rd party lng files
+*/
+
+// WavPack Input plugin (in_wv.dll)
+// {6DE2E465-690E-4df1-B6E2-2A9B33ED3DBB}
+static const GUID InWvLangGuid =
+{ 0x6de2e465, 0x690e, 0x4df1, { 0xb6, 0xe2, 0x2a, 0x9b, 0x33, 0xed, 0x3d, 0xbb } };
+
+// Nullsoft Waveform Wrapper plugin (in_wav.dll)
+// {1CED00E8-4B1B-4e10-A188-9A7C6BBEB421}
+static const GUID InWavLangGuid =
+{ 0x1ced00e8, 0x4b1b, 0x4e10, { 0xa1, 0x88, 0x9a, 0x7c, 0x6b, 0xbe, 0xb4, 0x21 } };
+
+// Jump To File Extra (JTFE) plugin (gen_jumpex.dll)
+// Note: this used to be {243355FE-8B16-48d2-89C3-FD80B3902875} but was changed with
+// v1.1 (the build in 5.58) due to mass of changes to the file to ensure that
+// this will work correctly if an old / partial file is present in the langpack
+// {4693FA7D-2055-4b36-A239-0AD998B5A884}
+static const GUID GenJTFELangGUID =
+{ 0x4693fa7d, 0x2055, 0x4b36, { 0xa2, 0x39, 0xa, 0xd9, 0x98, 0xb5, 0xa8, 0x84 } };
+
+// Time Restore & Autoplay (TRAP) plugin (gen_timerestore.dll)
+// {75854C46-1F1A-4fae-B3FA-EEA6B253490E}
+static const GUID GenTRAPLangGUID =
+{ 0x75854c46, 0x1f1a, 0x4fae, { 0xb3, 0xfa, 0xee, 0xa6, 0xb2, 0x53, 0x49, 0xe } };
+
+// Playlist File Remover (PLFR) plugin (gen_play_remove.dll)
+// {58D8276F-12DD-44a7-A930-AA336BC8BA9A}
+static const GUID GenPLFRLangGUID =
+{ 0x58d8276f, 0x12dd, 0x44a7, { 0xa9, 0x30, 0xaa, 0x33, 0x6b, 0xc8, 0xba, 0x9a } };
+
+// Skin Manager plugin (gen_skinmanager.dll)
+// {D877C116-0201-44b2-A003-335C0600BF7A}
+static const GUID GenSkinManagerGUID =
+{ 0xd877c116, 0x201, 0x44b2, { 0xa0, 0x3, 0x33, 0x5c, 0x6, 0x0, 0xbf, 0x7a } };
+
+// Playlist Undo plugin (gen_undo.dll)
+// {3050F3A7-DADB-459f-900A-A8A224B7F32D}
+static const GUID GenUndoLangGUID =
+{ 0x3050f3a7, 0xdadb, 0x459f, { 0x90, 0xa, 0xa8, 0xa2, 0x24, 0xb7, 0xf3, 0x2d } };
+
+// Playlist Separator plugin (in_text.dll)
+// {505CAF53-D00E-4580-AA67-B31DEA6FE946}
+static const GUID InTextLangGUID =
+{ 0x505caf53, 0xd00e, 0x4580, { 0xaa, 0x67, 0xb3, 0x1d, 0xea, 0x6f, 0xe9, 0x46 } };
+
+// One for Nunz plugin (gen_nunzio.dll)
+// {CB659857-7468-40ef-BC51-844449253780}
+static const GUID GenOne4NunzLangGUID =
+{ 0xcb659857, 0x7468, 0x40ef, { 0xbc, 0x51, 0x84, 0x44, 0x49, 0x25, 0x37, 0x80 } };
+
+// Save File As plugin (gen_saveas.dll)
+// {71174948-4965-4f61-90F5-E53FF30E6578}
+static const GUID GenSaveAsLangGUID =
+{ 0x71174948, 0x4965, 0x4f61, { 0x90, 0xf5, 0xe5, 0x3f, 0xf3, 0xe, 0x65, 0x78 } };
+
+// Yar-matey! Playlist Copier plugin (gen_yar.dll)
+// {9725C8BF-B577-4d72-93EF-5FB41D88FFC2}
+static const GUID GenYarLangGUID =
+{ 0x9725c8bf, 0xb577, 0x4d72, { 0x93, 0xef, 0x5f, 0xb4, 0x1d, 0x88, 0xff, 0xc2 } };
+
+// Album Art plugin (gen_classicart.dll)
+// {EAD1E933-6D75-4c2c-B9C4-B4D7F06B7D8D}
+static const GUID GenClasicArtGUID =
+{ 0xead1e933, 0x6d75, 0x4c2c, { 0xb9, 0xc4, 0xb4, 0xd7, 0xf0, 0x6b, 0x7d, 0x8d } };
+
+// Windows 7 Taskbar Integration plugin (gen_win7shell.dll)
+// {7204A532-5D37-415d-B431-272C953B7459}
+static const GUID GenWin7ShellLangGUID =
+{ 0x7204a532, 0x5d37, 0x415d, { 0xb4, 0x31, 0x27, 0x2c, 0x95, 0x3b, 0x74, 0x59 } };
+
+// Find File on Disk plugin (gen_find_on_disk.dll)
+// {8CCF206C-1EA0-484e-88A3-943B4C4AF272}
+static const GUID GenFFODLangGUID =
+{ 0x8ccf206c, 0x1ea0, 0x484e, { 0x88, 0xa3, 0x94, 0x3b, 0x4c, 0x4a, 0xf2, 0x72 } };
+
+// ML Bookmark Categoriser plugin (ml_bkmk.dll)
+// {C3BC5F81-B400-4c64-BCC5-3B758D6BE2E1}
+static const GUID MlBkCatLangGUID =
+{ 0xc3bc5f81, 0xb400, 0x4c64, { 0xbc, 0xc5, 0x3b, 0x75, 0x8d, 0x6b, 0xe2, 0xe1 } };
+
+// Lite'n Winamp Preferences plugin (gen_nopro.dll)
+// {E6C98DDD-FC99-4ccc-B845-79A81B8C1959}
+static const GUID GenNoProLangGUID =
+{ 0xe6c98ddd, 0xfc99, 0x4ccc, { 0xb8, 0x45, 0x79, 0xa8, 0x1b, 0x8c, 0x19, 0x59 } };
+
+// ML Enqueue & Play plugin (ml_enqplay.dll)
+// {0DF6B872-74C3-4236-BE78-E1EAE665C62D}
+static const GUID MlEnqPlayLangGUID =
+{ 0xdf6b872, 0x74c3, 0x4236, { 0xbe, 0x78, 0xe1, 0xea, 0xe6, 0x65, 0xc6, 0x2d } };
+
+// YMAMP (in_ym.dll)
+// {C5F9EFFA-4727-4075-9017-A6BAE72B848C}
+static const GUID InYMAMPLangGUID =
+{ 0xc5f9effa, 0x4727, 0x4075, { 0x90, 0x17, 0xa6, 0xba, 0xe7, 0x2b, 0x84, 0x8c } };
+
+// SNESAmp wrapper (in_snes.dll + in_snes.trb + in_snes_trb.lng)
+// {7B2084F6-B7A7-449b-A133-12F1916F188E}
+static const GUID InSNESWrapperLangGUID =
+{ 0x7b2084f6, 0xb7a7, 0x449b, { 0xa1, 0x33, 0x12, 0xf1, 0x91, 0x6f, 0x18, 0x8e } };
+
+// View Current File Information Hotkey (gen_wolfgang) plugin
+// {E16E2C50-71AB-4188-9193-B9D5FB127F97}
+static const GUID GenWolfgangLangGUID =
+{ 0xe16e2c50, 0x71ab, 0x4188, { 0x91, 0x93, 0xb9, 0xd5, 0xfb, 0x12, 0x7f, 0x97 } };
+
+// Mute Hotkey (gen_mute) plugin
+// {E87B8C7F-51DA-442c-BB2A-D5F941318853}
+static const GUID GenMuteLangGUID =
+{ 0xe87b8c7f, 0x51da, 0x442c, { 0xbb, 0x2a, 0xd5, 0xf9, 0x41, 0x31, 0x88, 0x53 } };
+
+// Play Random Song Hotkey (gen_prs) plugin
+// {1112230B-6928-4f20-BD0E-F559FE6AD66E}
+static const GUID GenPRSLangGUID =
+{ 0x1112230b, 0x6928, 0x4f20, { 0xbd, 0xe, 0xf5, 0x59, 0xfe, 0x6a, 0xd6, 0x6e } };
+
+// Randomise Playlist Hotkey (gen_grp) plugin
+// {554151CC-ADEC-4bdc-8A96-7812BF69058D}
+static const GUID GenRandPLLangGUID =
+{ 0x554151cc, 0xadec, 0x4bdc, { 0x8a, 0x96, 0x78, 0x12, 0xbf, 0x69, 0x5, 0x8d } };
+
+// Clear Current Playlist Hotkey (gen_gcp) plugin
+// {1C71FF32-D2E1-403b-B39C-897AF7F4B4AE}
+static const GUID GenCleardPLLangGUID =
+{ 0x1c71ff32, 0xd2e1, 0x403b, { 0xb3, 0x9c, 0x89, 0x7a, 0xf7, 0xf4, 0xb4, 0xae } };
+
+// EQ Hotkeys (gen_eq_hotkeys) plugin
+// {4EA319B6-955A-4519-807E-A36EEDDC6224}
+static const GUID GenEQGHKLangGUID =
+{ 0x4ea319b6, 0x955a, 0x4519, { 0x80, 0x7e, 0xa3, 0x6e, 0xed, 0xdc, 0x62, 0x24 } };
+
+// Auto EQ (gen_autoeq) plugin
+// {5A2E5855-239A-44a6-A49B-1F495BBFD0D6}
+static const GUID GenAutoEQLangGUID =
+{ 0x5a2e5855, 0x239a, 0x44a6, { 0xa4, 0x9b, 0x1f, 0x49, 0x5b, 0xbf, 0xd0, 0xd6 } };
+
+// CD Menu Tweaker (gen_cd_menu.dll)
+// {A609C17B-44F3-47d8-9B76-C660FF5D3739}
+static const GUID GenCDMenuTweakLangGUID =
+{ 0xa609c17b, 0x44f3, 0x47d8, { 0x9b, 0x76, 0xc6, 0x60, 0xff, 0x5d, 0x37, 0x39 } };
+
+// Three Mode Repeat (gen_3mode.dll)
+// {81EE2A10-80E9-4d22-B363-AEA820AE988F}
+static const GUID Gen3ModeLangGUID =
+{ 0x81ee2a10, 0x80e9, 0x4d22, { 0xb3, 0x63, 0xae, 0xa8, 0x20, 0xae, 0x98, 0x8f } };
+
+// Taskbar Text Mod (gen_ttm.dll)
+// {BBFD3662-DBDF-417a-AAAC-23914D55F24B}
+static const GUID GenTTMLangGUID =
+{ 0xbbfd3662, 0xdbdf, 0x417a, { 0xaa, 0xac, 0x23, 0x91, 0x4d, 0x55, 0xf2, 0x4b } };
+
+// OS Pos Restorer (gen_os_diag.dll)
+// {B5A3AD19-2180-45d7-AFFE-80D2B7575CD1}
+static const GUID GenOSDiagLangGUID =
+{ 0xb5a3ad19, 0x2180, 0x45d7, { 0xaf, 0xfe, 0x80, 0xd2, 0xb7, 0x57, 0x5c, 0xd1 } };
+
+// Shuffle Restorer (gen_shuffle_restorer.dll)
+// {B13ED906-B8E9-4753-B03F-351B05A6E250}
+static const GUID GenShuffleRestorerLangGUID =
+{ 0xb13ed906, 0xb8e9, 0x4753, { 0xb0, 0x3f, 0x35, 0x1b, 0x5, 0xa6, 0xe2, 0x50 } };
+
+// Shuffle Change Blocker (gen_shufblock.dll)
+// {FCCFABF2-6EF3-4651-A43C-F7CA38176889}
+static const GUID GenShuffleBlockerLangGUID =
+{ 0xfccfabf2, 0x6ef3, 0x4651, { 0xa4, 0x3c, 0xf7, 0xca, 0x38, 0x17, 0x68, 0x89 } };
+
+// Single Click 'n' Play (gen_singleclick.dll)
+// {AF67A1E2-8827-4fa3-9F9F-3A3DE2886022}
+static const GUID GenSingleClickLangGUID =
+{ 0xaf67a1e2, 0x8827, 0x4fa3, { 0x9f, 0x9f, 0x3a, 0x3d, 0xe2, 0x88, 0x60, 0x22 } };
+
+// No Minimise (gen_no_min.dll)
+// {8BCF7C51-6F88-455f-88FD-0B6911650997}
+static const GUID GenNoMinimiseLangGUID =
+{ 0x8bcf7c51, 0x6f88, 0x455f, { 0x88, 0xfd, 0xb, 0x69, 0x11, 0x65, 0x9, 0x97 } };
+
+// Repeater (gen_repeater.dll)
+// {1C4C8774-8BBC-4f11-851E-936BF5C85E96}
+static const GUID GenRepeaterLangGUID =
+{ 0x1c4c8774, 0x8bbc, 0x4f11, { 0x85, 0x1e, 0x93, 0x6b, 0xf5, 0xc8, 0x5e, 0x96 } };
+
+// Alt Close (gen_alt_close.dll)
+// {0FD70024-FA0E-4f4f-A0D4-CD560913C146}
+static const GUID GenAltCloseLangGUID =
+{ 0xfd70024, 0xfa0e, 0x4f4f, { 0xa0, 0xd4, 0xcd, 0x56, 0x9, 0x13, 0xc1, 0x46 } };
+
+// ML Exporter (ml_exporter.dll)
+// {3B441F40-E8E9-46bf-B399-556FB6CD4295}
+static const GUID MLExporterLangGUID =
+{ 0x3b441f40, 0xe8e9, 0x46bf, { 0xb3, 0x99, 0x55, 0x6f, 0xb6, 0xcd, 0x42, 0x95 } };
+
+// Silence Detector DSP (dsp_silence_detect.dll)
+// {15CCEBE6-C1F5-4246-A7B0-A6E66025C01C}
+static const GUID DspSilenceDetectLangGUID =
+{ 0x15ccebe6, 0xc1f5, 0x4246, { 0xa7, 0xb0, 0xa6, 0xe6, 0x60, 0x25, 0xc0, 0x1c } };
+
+// Skinned Preferences (gen_prefs_skin.dll)
+// {AE99B23F-0E51-4a99-9AB0-21AEA7B4B3CA}
+static const GUID GenSkinPrefsLangGUID =
+{ 0xae99b23f, 0xe51, 0x4a99, { 0x9a, 0xb0, 0x21, 0xae, 0xa7, 0xb4, 0xb3, 0xca } };
+
+// Jump to Track (gen_jtt.dll)
+// {D7D804A3-0794-4761-B43B-4873E5B41873}
+static const GUID GenJTTLangGUID =
+{ 0xd7d804a3, 0x794, 0x4761, { 0xb4, 0x3b, 0x48, 0x73, 0xe5, 0xb4, 0x18, 0x73 } };
+
+// Jump to Time Extra (gen_jumptotime.dll)
+// {9B5DC220-F06A-44cc-909E-D2157513F280}
+static const GUID GenJumpToTimeLangGUID =
+{ 0x9b5dc220, 0xf06a, 0x44cc, { 0x90, 0x9e, 0xd2, 0x15, 0x75, 0x13, 0xf2, 0x80 } };
+
+// Jumper (gen_jumper.dll)
+// {5D793BF9-0903-4bc9-A78D-D10AB92C7EE5}
+static const GUID GenJumperLangGUID =
+{ 0x5d793bf9, 0x903, 0x4bc9, { 0xa7, 0x8d, 0xd1, 0xa, 0xb9, 0x2c, 0x7e, 0xe5 } };
+
+// One Click Show and Hide (gen_one_click.dll)
+// {8F3FCFB3-1F5A-43c6-A71E-891026479301}
+static const GUID GenOneClickLangGUID =
+{ 0x8f3fcfb3, 0x1f5a, 0x43c6, { 0xa7, 0x1e, 0x89, 0x10, 0x26, 0x47, 0x93, 0x1 } };
+
+// Playback Excluder (gen_exclude.dll)
+// {15C44197-EBC5-4cc7-B935-EDE40C9C1AF6}
+static const GUID GenPlaybackExluderLangGUID =
+{ 0x15c44197, 0xebc5, 0x4cc7, { 0xb9, 0x35, 0xed, 0xe4, 0xc, 0x9c, 0x1a, 0xf6 } };
+
+// Close to Notification Area (gen_d3x7r0.dll)
+// {2A3BC93A-99FF-469a-A94B-576218CF6265}
+static const GUID GenCloseToNotAreaLangGUID =
+{ 0x2a3bc93a, 0x99ff, 0x469a, { 0xa9, 0x4b, 0x57, 0x62, 0x18, 0xcf, 0x62, 0x65 } };
+
+// Crop Die (gen_crop_die.dll)
+// {9E79066C-58C5-41b9-9361-C1951DA989CD}
+static const GUID GenCropDieLangGUID =
+{ 0x9e79066c, 0x58c5, 0x41b9, { 0x93, 0x61, 0xc1, 0x95, 0x1d, 0xa9, 0x89, 0xcd } };
+
+// Play Selected Song Hotkey (gen_gpss.dll)
+// {94E8B2B6-685F-484b-9938-EC929F6874EC}
+static const GUID GenPlaySelGHKLangGUID =
+{ 0x94e8b2b6, 0x685f, 0x484b, { 0x99, 0x38, 0xec, 0x92, 0x9f, 0x68, 0x74, 0xec } };
+
+// Close After Current (gen_cac.dll)
+// {8B6A33FB-A6C5-49a0-A52A-0A0F14913BB2}
+static const GUID GenCACLangGUID =
+{ 0x8b6a33fb, 0xa6c5, 0x49a0, { 0xa5, 0x2a, 0xa, 0xf, 0x14, 0x91, 0x3b, 0xb2 } };
+
+// Enhancer Wrapper DSP (dsp_enhancer.dll)
+// {78842EF6-CCA2-410c-9E23-C498ABB24373}
+static const GUID DspEnhancerLangGUID =
+{ 0x78842ef6, 0xcca2, 0x410c, { 0x9e, 0x23, 0xc4, 0x98, 0xab, 0xb2, 0x43, 0x73 } };
+
+// Shutdown on Close (gen_soc.dll)
+// {CAE88304-4A0B-46e5-8B50-BEDFAE00FA6A}
+static const GUID GenSOCLangGUID =
+{ 0xcae88304, 0x4a0b, 0x46e5, { 0x8b, 0x50, 0xbe, 0xdf, 0xae, 0x0, 0xfa, 0x6a } };
+
+// Mouse Wheel Blocker (gen_mwblock.dll)
+// {C9D6697C-4C7B-4aec-A4C7-45395F0771EA}
+static const GUID GenMouseWheelBlockLangGUID =
+{ 0xc9d6697c, 0x4c7b, 0x4aec, { 0xa4, 0xc7, 0x45, 0x39, 0x5f, 0x7, 0x71, 0xea } };
+
+// ML Icon Control plugin (ml_icon_control.dll)
+// {4A55AE4D-B3CB-42df-A94E-53588FD761BA}
+static const GUID MlIconControlLangGUID=
+{ 0x4a55ae4d, 0xb3cb, 0x42df, { 0xa9, 0x4e, 0x53, 0x58, 0x8f, 0xd7, 0x61, 0xba } };
+
+// File Copier plug-in (gen_copy.dll)
+// {A2121FC9-6FC3-4a56-88F2-A36FF64D10EA}
+static const GUID GenFileCopierLangGUID =
+{ 0xa2121fc9, 0x6fc3, 0x4a56, { 0x88, 0xf2, 0xa3, 0x6f, 0xf6, 0x4d, 0x10, 0xea } };
+
+// Shoutcast Source DSP plug-in
+// Note: this used to be {FD4D4A01-C337-4144-85D7-00678B3B2D2D} but was changed with
+// v2.3.0 due to mass of changes to the file to ensure that this will work
+// correctly if an old / partial file is present in the langpack
+// {88380E65-4068-49BA-8EA4-3F2AF12D0A4F}
+static const GUID DspShoutcastLangGUID =
+{ 0x88380e65, 0x4068, 0x49ba, { 0x8e, 0xa4, 0x3f, 0x2a, 0xf1, 0x2d, 0xa, 0x4f } };
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+#endif \ No newline at end of file
diff --git a/Src/Agave/Metadata/api_metadata.cpp b/Src/Agave/Metadata/api_metadata.cpp
new file mode 100644
index 00000000..1eedadb9
--- /dev/null
+++ b/Src/Agave/Metadata/api_metadata.cpp
@@ -0,0 +1 @@
+#include "api_metadata.h" \ No newline at end of file
diff --git a/Src/Agave/Metadata/api_metadata.h b/Src/Agave/Metadata/api_metadata.h
new file mode 100644
index 00000000..da3c2145
--- /dev/null
+++ b/Src/Agave/Metadata/api_metadata.h
@@ -0,0 +1,102 @@
+#ifndef NULLSOFT_AGAVE_METADATA_API_METADATA_H
+#define NULLSOFT_AGAVE_METADATA_API_METADATA_H
+
+/**
+ ** Author: Ben Allison
+ ** original date: April 10, 2006
+ */
+#include <bfc/dispatch.h>
+#include "svc_metatag.h"
+
+
+class api_metadata : public Dispatchable
+{
+protected:
+ api_metadata() {}
+ ~api_metadata() {}
+
+public:
+ // replacement for IPC_GET_EXTENDED_FILE_INFO, it's slow, so only use for converting old code, or one-off metadata grabbing
+ int GetExtendedFileInfo(const wchar_t *filename, const wchar_t *tag, wchar_t *data, size_t dataLength);
+
+ // replacement for IPC_SET_EXTENDED_FILE_INFO
+ int SetExtendedFileInfo(const wchar_t *filename, const wchar_t *tag, const wchar_t *data);
+ int WriteExtendedFileInfo(const wchar_t *filename);
+
+ /** faster methods below. these return you an object that you can keep re-using (for a single file)
+ ** it's still your job to call svc_metaTag::metaTag_open() - see note [2]
+ ** call svc_metaTag::close() when you're done - see note [3]
+ */
+ svc_metaTag *GetMetaTagObject(const wchar_t *filename, int flags=METATAG_ALL, GUID *exclude=0, int numExcludes=0); // see note [1]
+ svc_metaTag *GetMetaTagObject(const GUID metaTagGuid); // gets a specific svc_metaTag object by GUID
+
+ /**
+ ** Retrieves a unique key for a given field name
+ ** if one already exists, that index is returned
+ ** returns -1 on failure/not implemented
+ **/
+ uint32_t GenerateKey(const wchar_t *field);
+
+
+ DISPATCH_CODES
+ {
+ API_METADATA_GETEXTENDEDFILEINFO = 10,
+ API_METADATA_SETEXTENDEDFILEINFO = 11,
+ API_METADATA_WRITEEXTENDEDFILEINFO = 12,
+ API_METADATA_GETMETATAGOBJECT = 20,
+ API_METADATA_GETMETATAGOBJECTBYGUID = 30,
+ API_METADATA_GENERATEKEY = 40,
+ };
+};
+
+/**
+ ** [1] flags can be set to only use certain metadata providers, file info, database, online lookup (CDDB, etc), guessing
+ ** exclude list can be use to exclude certain metatag GUIDs. This is useful for metadata services that need to look up metadata themselves
+ ** e.g. CDDB might need to get a Disc ID, media library wants to ask for info to fill itself in. Neither services wants to have themselves
+ ** be asked, and might not want a "guessing" metatag provider to be used, either.
+ ** [2] these methods could technically open the file also, but we've left that out to allow for some flexibility
+ ** e.g. someone might just be looking for the metaTag service name or GUID.
+ ** [3] you need to close it even if you never opened it. This allows the object to "self-destruct".
+ ** If we didn't do this, we would also have to pass back the service factory
+ **
+ */
+
+inline int api_metadata::GetExtendedFileInfo(const wchar_t *filename, const wchar_t *tag, wchar_t *data, size_t dataLength)
+{
+ return _call(API_METADATA_GETEXTENDEDFILEINFO, (int)0, filename, tag, data, dataLength);
+}
+
+inline int api_metadata::SetExtendedFileInfo(const wchar_t *filename, const wchar_t *tag, const wchar_t *data)
+{
+ return _call(API_METADATA_SETEXTENDEDFILEINFO, (int)0, filename, tag, data);
+}
+
+inline int api_metadata::WriteExtendedFileInfo(const wchar_t *filename)
+{
+ return _call(API_METADATA_WRITEEXTENDEDFILEINFO, (int)0, filename);
+}
+
+
+inline svc_metaTag *api_metadata::GetMetaTagObject(const wchar_t *filename, int flags, GUID *exclude, int numExcludes)
+{
+ return _call(API_METADATA_GETMETATAGOBJECT, (svc_metaTag *)NULL, filename, flags, exclude, numExcludes);
+}
+
+inline svc_metaTag *api_metadata::GetMetaTagObject(const GUID metaTagGuid)
+{
+ return _call(API_METADATA_GETMETATAGOBJECTBYGUID, (svc_metaTag *)NULL, metaTagGuid);
+}
+
+#pragma warning(push)
+#pragma warning(disable : 4267)
+inline uint32_t api_metadata::GenerateKey(const wchar_t *field)
+{
+ return _call(API_METADATA_GENERATEKEY, (uint32_t)-1);
+}
+#pragma warning(pop)
+
+// {DFA89F63-995A-407b-8BC8-827900440727}
+static const GUID api_metadataGUID =
+{ 0xdfa89f63, 0x995a, 0x407b, { 0x8b, 0xc8, 0x82, 0x79, 0x0, 0x44, 0x7, 0x27 } };
+
+#endif
diff --git a/Src/Agave/Metadata/ifc_metadataReader.h b/Src/Agave/Metadata/ifc_metadataReader.h
new file mode 100644
index 00000000..16749795
--- /dev/null
+++ b/Src/Agave/Metadata/ifc_metadataReader.h
@@ -0,0 +1,107 @@
+#ifndef NULLSOFT_AGAVE_METADATA_IFC_METADATAREADER_H
+#define NULLSOFT_AGAVE_METADATA_IFC_METADATAREADER_H
+
+#include <bfc/dispatch.h>
+
+class ifc_metadataReader : public Dispatchable
+{
+protected:
+ ifc_metadataReader()
+ {}
+ ~ifc_metadataReader()
+ {}
+public:
+ /* If there are multiple values for the same field, these functions will concatenate the values in some
+ manner as defined by the language pack */
+ int GetField( const wchar_t *field, wchar_t *destination, size_t destinationCch );
+ int GetFieldByKey( uint32_t field_key, wchar_t *destination, size_t destinationCch );
+
+ int GetIndexedField( const wchar_t *field, uint32_t index, wchar_t *destination, size_t destinationCch );
+ int GetIndexedFieldByKey( uint32_t field_key, uint32_t index, wchar_t *destination, size_t destinationCch );
+
+ class ifc_fieldEnumerator : public Dispatchable
+ {
+ protected:
+ ifc_fieldEnumerator();
+ ~ifc_fieldEnumerator();
+
+ public:
+ const wchar_t *GetField();
+ uint32_t GetKey();
+ int Next();
+
+ DISPATCH_CODES
+ {
+ DISP_GETFIELD = 0,
+ DISP_GETKEY = 1,
+ DISP_NEXT = 2,
+ };
+
+ };
+
+ enum
+ {
+ ENUMERATORFLAG_MULTIPLE_FIELDS = 0, // if multiple values of the same field are present, return each one
+ ENUMERATORFLAG_REMOVE_DUPLICATE_FIELDS = 1, // don't enumerate duplicate fields (with differing values)
+ };
+
+ ifc_fieldEnumerator *GetFieldEnumerator( int flags = ENUMERATORFLAG_MULTIPLE_FIELDS ); // Enumerate fields present in this file
+
+ DISPATCH_CODES
+ {
+ DISP_GETFIELD = 0,
+ DISP_GETFIELDKEY = 1,
+ DISP_GETINDEXEDFIELD = 2,
+ DISP_GETINDEXEDFIELDBYKEY = 3,
+ DISP_GETFIELDENUMERATOR = 4,
+ };
+
+ enum
+ {
+ NOT_IMPLEMENTED = -1,
+ SUCCESS = 0,
+ FAILURE = 1,
+ END_OF_ITERATOR = 2,
+ };
+};
+
+inline int ifc_metadataReader::GetField(const wchar_t *field, wchar_t *destination, size_t destinationCch)
+{
+ return _call(DISP_GETFIELD, (int)ifc_metadataReader::NOT_IMPLEMENTED, field, destination, destinationCch);
+}
+
+inline int ifc_metadataReader::GetFieldByKey(uint32_t field_key, wchar_t *destination, size_t destinationCch)
+{
+ return _call(DISP_GETFIELDKEY, (int)ifc_metadataReader::NOT_IMPLEMENTED, field_key, destination, destinationCch);
+}
+
+inline int ifc_metadataReader::GetIndexedField(const wchar_t *field, uint32_t index, wchar_t *destination, size_t destinationCch)
+{
+ return _call(DISP_GETINDEXEDFIELD, (int)ifc_metadataReader::NOT_IMPLEMENTED, field, index, destination, destinationCch);
+}
+
+inline int ifc_metadataReader::GetIndexedFieldByKey(uint32_t field_key, uint32_t index, wchar_t *destination, size_t destinationCch)
+{
+ return _call(DISP_GETINDEXEDFIELDBYKEY, (int)ifc_metadataReader::NOT_IMPLEMENTED, field_key, index, destination, destinationCch);
+}
+
+inline ifc_metadataReader::ifc_fieldEnumerator *ifc_metadataReader::GetFieldEnumerator(int flags)
+{
+ return _call(DISP_GETFIELDENUMERATOR, (ifc_metadataReader::ifc_fieldEnumerator *)0, flags);
+}
+
+inline const wchar_t *ifc_metadataReader::ifc_fieldEnumerator::GetField()
+{
+ return _call(DISP_NEXT, (const wchar_t *)0);
+}
+
+inline uint32_t ifc_metadataReader::ifc_fieldEnumerator::GetKey()
+{
+ return _call(DISP_NEXT, (int)ifc_metadataReader::NOT_IMPLEMENTED);
+}
+
+inline int ifc_metadataReader::ifc_fieldEnumerator::Next()
+{
+ return _call(DISP_NEXT, (int)END_OF_ITERATOR);
+}
+#endif \ No newline at end of file
diff --git a/Src/Agave/Metadata/svc_metatag.h b/Src/Agave/Metadata/svc_metatag.h
new file mode 100644
index 00000000..0f633926
--- /dev/null
+++ b/Src/Agave/Metadata/svc_metatag.h
@@ -0,0 +1,152 @@
+#ifndef NULLSOFT_AGAVE_SVC_METATAG_H
+#define NULLSOFT_AGAVE_SVC_METATAG_H
+
+/**
+ ** Author: Ben Allison
+ ** original date: April 10, 2006
+ */
+#include <bfc/dispatch.h>
+#include <api/service/services.h>
+#include <bfc/platform/types.h>
+#include <bfc/std_mkncc.h> // for MKnCC()
+
+/* these two GUIDs are to allow you to QueryInterface between readers and writers */
+// {9FD00FBE-B707-4743-B630-CC14071EA443}
+static const GUID AgaveMetadataReaderIID =
+{ 0x9fd00fbe, 0xb707, 0x4743, { 0xb6, 0x30, 0xcc, 0x14, 0x7, 0x1e, 0xa4, 0x43 } };
+
+// {3444E4AD-D6B3-4ac4-A08D-C3F935DC7B98}
+static const GUID AgaveMetadataWriterIID =
+{ 0x3444e4ad, 0xd6b3, 0x4ac4, { 0xa0, 0x8d, 0xc3, 0xf9, 0x35, 0xdc, 0x7b, 0x98 } };
+
+enum
+{
+ METATAG_SUCCESS = 0,
+ METATAG_FAILED = 1,
+
+ METATAG_UNKNOWN_TAG = 2, // the tag name isn't understood
+ METATAG_NO_METADATA = 3, // returned if the file has no metadata at all
+ METATAG_NOT_APPLICABLE = 4,
+
+};
+
+enum
+{
+ METATYPE_STRING = 0, // always unicode! and always null terminated
+ METATYPE_FILENAME = 0,
+ METATYPE_INTEGER = 1,
+ METATYPE_UNSIGNED = 2,
+ METATYPE_SIZE = 2,
+ METATYPE_GUID = 3,
+ METATYPE_BINARY = 4,
+};
+
+// flags
+enum
+{
+ METATAG_FILE_INFO = 0x1,
+ METATAG_ONLINE_LOOKUP = 0x2,
+ METATAG_CACHE_DB = 0x4,
+ METATAG_GUESS = 0x8,
+ METATAG_ALL = 0xFFFFFFFF
+};
+
+class svc_metaTag : public Dispatchable
+{
+protected:
+ svc_metaTag() {}
+ ~svc_metaTag() {}
+
+public:
+ /* These methods are to be used by api_metadata */
+ static FOURCC getServiceType() { return svc_metaTag::SERVICETYPE; }
+ const wchar_t *getName(); // i.e. "ID3v2" or something
+ GUID getGUID(); // this needs to be the same GUID that you use when registering your service factory
+ int getFlags(); // how this service gets its info
+ int isOurFile(const wchar_t *filename);
+ int metaTag_open(const wchar_t *filename);
+ void metaTag_close(); // self-destructs when this is called (you don't need to call serviceFactory->releaseInterface)
+
+ /* user API starts here */
+ const wchar_t *enumSupportedTag(int n, int *datatype = NULL); // returns a list of understood tags. might not be complete (see note [1])
+ int getTagSize(const wchar_t *tag, size_t *sizeBytes); // always gives you BYTES, not characters (be careful with your strings)
+ int getMetaData(const wchar_t *tag, uint8_t *buf, int buflenBytes, int datatype = METATYPE_STRING); // buflen is BYTES, not characters (be careful with your strings)
+ int setMetaData(const wchar_t *tag, const uint8_t *buf, int buflenBytes, int datatype = METATYPE_STRING);
+public:
+ DISPATCH_CODES
+ {
+ SVC_METATAG_GETNAME = 10,
+ SVC_METATAG_GETGUID = 20,
+ SVC_METATAG_GETFLAGS = 30,
+ SVC_METATAG_ISOURFILE = 40,
+ SVC_METATAG_OPEN = 50,
+ SVC_METATAG_CLOSE = 60,
+ SVC_METATAG_ENUMTAGS = 100,
+ SVC_METATAG_GETTAGSIZE = 110,
+ SVC_METATAG_GETMETADATA = 120,
+ SVC_METATAG_SETMETADATA = 130,
+
+ };
+ enum
+ {
+ SERVICETYPE = MK4CC('m','t','t','g')
+ };
+};
+
+/** Notes:
+ ** [1] Many metadata getters rely on an underlying library, and some metadata systems (e.g. Vorbis) are open-ended. As a result, there might be no way of
+ ** generating a complete list
+*/
+
+inline const wchar_t *svc_metaTag::getName()
+{
+ return _call(SVC_METATAG_GETNAME, (const wchar_t*)NULL);
+}
+
+inline GUID svc_metaTag::getGUID()
+{
+ return _call(SVC_METATAG_GETGUID, GUID_NULL);
+}
+
+inline int svc_metaTag::getFlags()
+{
+ return _call(SVC_METATAG_GETFLAGS, 0);
+}
+
+inline int svc_metaTag::isOurFile(const wchar_t *filename)
+{
+ return _call(SVC_METATAG_ISOURFILE, (int)0, filename);
+}
+
+inline int svc_metaTag::metaTag_open(const wchar_t *filename)
+{
+ return _call(SVC_METATAG_OPEN, (int)METATAG_FAILED, filename);
+}
+
+inline void svc_metaTag::metaTag_close()
+{
+ _voidcall(SVC_METATAG_CLOSE);
+}
+
+inline const wchar_t *svc_metaTag::enumSupportedTag(int n, int *datatype)
+{
+ return _call(SVC_METATAG_ENUMTAGS, (const wchar_t *)NULL, n, datatype);
+}
+
+inline int svc_metaTag::getTagSize(const wchar_t *tag, size_t *sizeBytes)
+{
+ return _call(SVC_METATAG_GETTAGSIZE, (int)0, tag, sizeBytes);
+}
+
+inline int svc_metaTag::getMetaData(const wchar_t *tag, uint8_t *buf, int buflenBytes, int datatype)
+{
+ return _call(SVC_METATAG_GETMETADATA, (int)METATAG_FAILED, tag, buf, buflenBytes, datatype);
+}
+
+inline int svc_metaTag::setMetaData(const wchar_t *tag, const uint8_t *buf, int buflenBytes, int datatype)
+{
+ return _call(SVC_METATAG_SETMETADATA, (int)METATAG_FAILED, tag, buf, buflenBytes, datatype);
+}
+
+
+#endif
diff --git a/Src/Agave/PlaylistColouriser/api_playlist_colouriser.h b/Src/Agave/PlaylistColouriser/api_playlist_colouriser.h
new file mode 100644
index 00000000..7e1ebddf
--- /dev/null
+++ b/Src/Agave/PlaylistColouriser/api_playlist_colouriser.h
@@ -0,0 +1,154 @@
+#ifndef NULLSOFT_API_PLAYLIST_COLOURISER_H
+#define NULLSOFT_API_PLAYLIST_COLOURISER_H
+
+/*
+** Wasabi Playlist Colouriser API Interface v1.0
+** Note: This requires JTFE v1.2 and higher to work
+** (Released: 28/09/2010)
+**
+**
+** This header file provides the interfaces implemented by the JTFE plugin for other plugins and services to
+** be able to make use of it's playlist colouriser which allows for highlighting of playlist entries in a
+** different style to that currently defined by the skin in use to make for example queued items more visible.
+**
+** The interface allows for controlling aspects of the text colour and the background of playlist item entries
+** as long as they exist in the playlist editor or there is data to show e.g. you cannot change the text colour
+** of the time entry if there is no time entry shown such as for missing files or streams of unknown length).
+**
+** When specifying a colour, if you want the default skin colours to be used then you need to set the colour to
+** be -1
+**
+** To use this api assumes you know already how to make use of the wasabi service based system
+** (see the more complete examples provided in the SDK).
+**
+**
+** Example:
+**
+** The following psuedo code shows how to show a flashing inverted selection on the first item being queried in
+** the current playlist editor's contents.
+**
+** // this will setup an inverted entry when the playlist is queried to be painted
+** // you could setup a timer to cause a playlist painting event to make it flash
+** // if you toggle the returned state on and off in the ExampleCheck(..) callback
+** Colouriser ExampleColouriser = {COLOURISER_FULL_BKGND | COLOURISER_FULL_TEXT |
+** COLOURISER_INVERTED | COLOURISER_INVERTED_TEXT,
+** 0,-1,-1,-1,-1, ExampleCheck};
+**
+** int ExampleCheck(int idx, wchar_t* file){
+** // will only apply the colouring on the first playlist item
+** return (idx == 0);
+** }
+**
+** // use this to get an instance of the service (returns null or 1 on error or not supported)
+** if(!WASABI_API_COLOURISER) ServiceBuild(WASABI_API_COLOURISER,PlaylistColouriserApiGUID);
+**
+**
+** // this can be used to add or update an existing colouriser instance
+** // using COLOURISER_DISABLED in the flags to disable it if not needed
+** if(!WASABI_API_COLOURISER->ColouriserExists(&ExampleColouriser)){
+** WASABI_API_COLOURISER->AddColouriser(&ExampleColouriser);
+** }
+** else{
+** WASABI_API_COLOURISER->UpdateColouriser(&ExampleColouriser);
+** }
+**
+** // with the above, if you wanted to change the code to just change the text
+** // colour of playlist item then you could use something like the following:
+** ExampleColouriser.flags = COLOURISER_FULL_TEXT;
+** ExampleColouriser.main_text = ExcludeColouriser.time_text = <specify_your_colour>;
+*/
+
+#if (_MSC_VER <= 1200)
+typedef int intptr_t;
+#endif
+
+#ifdef __cplusplus
+
+#include <bfc/dispatch.h>
+
+typedef struct{
+ #define COLOURISER_TIME_BKGND 0x01 // override the time column background colour - uses time_bkgnd
+ #define COLOURISER_MAIN_BKGND 0x02 // override the main column background colour - uses main_bkgnd
+ #define COLOURISER_MAIN_BKGND_ALT 0x04 // allows for a different colour for the main column background
+ #define COLOURISER_FULL_BKGND COLOURISER_MAIN_BKGND | COLOURISER_TIME_BKGND
+
+ #define COLOURISER_TIME_TEXT 0x10 // override the time column text colour - uses time_text
+ #define COLOURISER_MAIN_TEXT 0x20 // override the main column text colour - uses main_text
+ #define COLOURISER_FULL_TEXT COLOURISER_TIME_TEXT | COLOURISER_MAIN_TEXT
+
+ #define COLOURISER_BLEND 0x40 // will attempt to blend the colour with the existing colours
+
+ #define COLOURISER_DISABLED 0x1000 // set this when you require your colouriser to be ignored
+ #define COLOURISER_INVERTED 0x2000 // if colours are specified as -1 then use the inverse of the current skin values
+ #define COLOURISER_INVERTED_TEXT 0x4000 // if colours are specified as -1 then use the inverse of the current skin values
+ // this will only be used if COLOURISER_INVERTED is already specified
+
+ int flags; // determine which colours are to be used / handled
+ int _me; // used to identify the colouriser - don't alter!!!
+
+ // when using ColouriserColour(..) the value for query_colour is shown to the right
+ COLORREF time_bkgnd; // 0
+ COLORREF main_bkgnd; // 1
+ COLORREF time_text; // 2
+ COLORREF main_text; // 3
+
+ // callback function to see if the colouriser's colours need to be used on the passed playlist item
+ int (*check)(int entry_index, wchar_t* entry_filepath);
+} Colouriser;
+
+class api_playlist_colouriser : public Dispatchable
+{
+protected:
+ api_playlist_colouriser() {}
+ ~api_playlist_colouriser() {}
+
+public:
+ BOOL AddColouriser(Colouriser* colouriser);
+ Colouriser* UpdateColouriser(Colouriser* colouriser);
+ BOOL ColourPicker(HWND parent_hwnd, UINT control_id, UINT options_id, Colouriser* colouriser, wchar_t* window_title, wchar_t* button_text);
+ BOOL ColouriserExists(Colouriser* colouriser);
+ COLORREF ColouriserColour(COLORREF current_colour, UINT query_colour);
+
+public:
+ DISPATCH_CODES
+ {
+ API_COLOURISER_ADD = 1,
+ API_COLOURISER_UPDATE = 2,
+ API_COLOURISER_COLOURPICKER = 3,
+ API_COLOURISER_EXISTS = 4,
+ API_COLOURISER_COLOUR = 5,
+ };
+};
+
+inline BOOL api_playlist_colouriser::AddColouriser(Colouriser* colouriser)
+{
+ return _call(API_COLOURISER_ADD, (BOOL)0, colouriser);
+}
+
+inline Colouriser* api_playlist_colouriser::UpdateColouriser(Colouriser* colouriser)
+{
+ return _call(API_COLOURISER_UPDATE, (Colouriser*)0, colouriser);
+}
+
+inline BOOL api_playlist_colouriser::ColourPicker(HWND parent_hwnd, UINT control_id, UINT options_id, Colouriser* colouriser, wchar_t* window_title, wchar_t* button_text)
+{
+ return _call(API_COLOURISER_COLOURPICKER, (BOOL)0, parent_hwnd, control_id, options_id, colouriser, window_title, button_text);
+}
+
+inline BOOL api_playlist_colouriser::ColouriserExists(Colouriser* colouriser)
+{
+ return _call(API_COLOURISER_EXISTS, (BOOL)0, colouriser);
+}
+
+inline COLORREF api_playlist_colouriser::ColouriserColour(COLORREF current_colour, UINT query_colour)
+{
+ return _call(API_COLOURISER_COLOUR, (COLORREF)0, current_colour, query_colour);
+}
+
+#endif
+
+// {B8B8DA7C-1F35-4a6d-95FA-C7E9651D5DC0}
+static const GUID PlaylistColouriserApiGUID =
+{ 0xb8b8da7c, 0x1f35, 0x4a6d, { 0x95, 0xfa, 0xc7, 0xe9, 0x65, 0x1d, 0x5d, 0xc0 } };
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Queue/api_queue.h b/Src/Agave/Queue/api_queue.h
new file mode 100644
index 00000000..272ced86
--- /dev/null
+++ b/Src/Agave/Queue/api_queue.h
@@ -0,0 +1,202 @@
+#ifndef NULLSOFT_API_QUEUE_H
+#define NULLSOFT_API_QUEUE_H
+
+/*
+** JTFE v1.0.1 Wasabi API interface
+** (Released: 06/01/2010)
+**
+**
+** This header file provides the interfaces implemented by the JTFE plugin for other plugins/services to be able
+** to make use of it's queue which allows for Winamp's playback order to be overriden.
+**
+** To use this api assumes you know already how to make use of the wasabi service based system
+** (see the more complete examples provided in the SDK).
+**
+**
+** Example:
+**
+** The following psuedo code shows how to clear the current queue (if one exists) and will then add in a specifc
+** file by the full path passed and also adding a file based on the position in the current playlist.
+**
+** if(!WASABI_API_QUEUEMGR) ServiceBuild(WASABI_API_QUEUEMGR,QueueManagerApiGUID);
+** if(WASABI_API_QUEUEMGR){
+** // Clear the queue (if one exists)
+** WASABI_API_QUEUEMGR->ClearQueue();
+**
+** // Add the full file path (wchar_t_path_to_file)
+** WASABI_API_QUEUEMGR->AddItemToQueue(0,1,wchar_t_path_to_file);
+**
+** // Add the first file in the playlist editor into the queue
+** WASABI_API_QUEUEMGR->AddItemToQueue(0,0,0);
+** }
+**
+**
+** Notes:
+**
+** This header only provides access to the functions it exports. Some actions like the MoveQueuedItem(s) functions
+** have not been implemented in this api even though they are internally implemented. In future releases of the
+** plugin it is hoped that these (and another useful/requested) apis will also be implemented and provided.
+**
+** Changes:
+** v1.0.1 - Fixes EnableQueueAdvance(..) and IsQueueAdvanceEnabled(..) interfaces not correctly defined in this file
+** - Fixes crash when calling IsQueueAdvanceEnabled(..) (if previous issue was manually corrected)
+**
+*/
+
+#if (_MSC_VER <= 1200)
+typedef int intptr_t;
+#endif
+
+enum PLAYLIST_TYPE {M3U_PLAYLIST=0x0, PLS_PLAYLIST=0x1, M3U8_PLAYLIST=0x2};
+enum MOVE_MODE {MOVE_TOP_OF_LIST=-2, MOVE_UP_LIST=-1, MOVE_DOWN_LIST=1, MOVE_END_OF_LIST=2, MOVE_END_TO_START=3 };
+
+#ifdef __cplusplus
+
+#include <bfc/dispatch.h>
+
+class api_queue : public Dispatchable
+{
+protected:
+ api_queue() {}
+ ~api_queue() {}
+
+public:
+ // main handling functions of the queue to add/remove/clear all
+ BOOL AddItemToQueue(int item, int update_now, wchar_t* file);
+ void RemoveQueuedItem(int item, int no_update=0);
+ void ClearQueue(void);
+
+ /*
+ ** handling functions to allow for querying/manipulating of the queue items
+ ** note: need to have a consistancy in the functions and all that...
+ **
+ ** use GetNumberOfQueuedItems() and then loop upto that via GetQueuedItemFromIndex(..) to get item id of the queue
+ */
+ int GetNumberOfQueuedItems(void);
+ int GetQueuedItemFromIndex(int idx);
+ wchar_t* GetQueuedItemFilePath(int item);
+ int GetQueuedItemPlaylistPosition(int item);
+ int IsItemQueuedMultipleTimes(int item, int test_only); // returns how many times an item is showing in the queue
+
+ // Note: these are to be implemented after JTFE 1.0
+ //BOOL MoveQueuedItem(int item, int mode/*MOVE_MODE*/);
+ //BOOL MoveQueuedItems(int* items, int mode/*MOVE_MODE*/);
+
+ /*
+ ** miscellaneous actions available on the queue
+ */
+ void RandomiseQueue(void);
+ // will ignore the item position and match it up against the current playlist (may cause queued item position merging)
+ void RefreshQueue(void);
+ BOOL LoadPlaylistIntoQueue(wchar_t* playlist_file, int reset_queue);
+ BOOL SaveQueueToPlaylist(wchar_t* playlist_file, int playlist_type/*PLAYLIST_TYPE*/);
+
+ // enables/disables queue advancement and query this state
+ int EnableQueueAdvance(int enabled);
+ int IsQueueAdvanceEnabled(void);
+
+public:
+ DISPATCH_CODES
+ {
+ API_QUEUE_ADDITEMTOQUEUE = 1,
+ API_QUEUE_REMOVEQUEUEDITEM = 2,
+ API_QUEUE_CLEARQUEUE = 3,
+
+ API_QUEUE_GETNUMBEROFQUEUEDITEMS = 10,
+ API_QUEUE_GETQUEUEDITEMFROMINDEX = 11,
+ API_QUEUE_GETQUEUEDITEMFILEPATH = 12,
+ API_QUEUE_GETQUEUEDITEMPLAYLISTPOSITION = 13,
+ API_QUEUE_ISITEMQUEUEDMULTIPLETIMES = 14,
+
+ // Note: to be implemented after JTFE 1.0
+ //API_QUEUE_MOVEQUEUEDITEM = 15,
+ //API_QUEUE_MOVEQUEUEDITEMS = 16,
+
+ API_QUEUE_RANDOMISEQUEUE = 20,
+ API_QUEUE_REFRESHQUEUE = 21,
+ API_QUEUE_LOADPLAYLISTINTOQUEUE = 22,
+ API_QUEUE_SAVEQUEUETOPLAYLIST = 23,
+
+ API_QUEUE_ENABLEQUEUEADVANCE = 30,
+ API_QUEUE_ISQUEUEADVANCEENABLED = 31
+ };
+};
+
+inline BOOL api_queue::AddItemToQueue(int item, int update_now, wchar_t* file)
+{
+ return _call(API_QUEUE_ADDITEMTOQUEUE, (BOOL)0, item, update_now, file);
+}
+
+inline void api_queue::RemoveQueuedItem(int item, int no_update)
+{
+ _voidcall(API_QUEUE_REMOVEQUEUEDITEM, item, no_update);
+}
+
+inline void api_queue::ClearQueue(void)
+{
+ _voidcall(API_QUEUE_CLEARQUEUE);
+}
+
+inline int api_queue::GetNumberOfQueuedItems(void)
+{
+ return _call(API_QUEUE_GETNUMBEROFQUEUEDITEMS, (int)0);
+}
+
+inline int api_queue::GetQueuedItemFromIndex(int idx)
+{
+ return _call(API_QUEUE_GETQUEUEDITEMFROMINDEX, (int)0, idx);
+}
+
+inline wchar_t* api_queue::GetQueuedItemFilePath(int item)
+{
+ return _call(API_QUEUE_GETQUEUEDITEMFILEPATH, (wchar_t*)0, item);
+}
+
+inline int api_queue::GetQueuedItemPlaylistPosition(int item)
+{
+ return _call(API_QUEUE_GETQUEUEDITEMPLAYLISTPOSITION, (int)0, item);
+}
+
+inline int api_queue::IsItemQueuedMultipleTimes(int item, int test_only)
+{
+ return _call(API_QUEUE_ISITEMQUEUEDMULTIPLETIMES, (int)0, item, test_only);
+}
+
+inline void api_queue::RandomiseQueue(void)
+{
+ _voidcall(API_QUEUE_RANDOMISEQUEUE);
+}
+
+inline void api_queue::RefreshQueue(void)
+{
+ _voidcall(API_QUEUE_REFRESHQUEUE);
+}
+
+inline int api_queue::LoadPlaylistIntoQueue(wchar_t* playlist_file, int reset_queue)
+{
+ return _call(API_QUEUE_LOADPLAYLISTINTOQUEUE, (int)0, playlist_file, reset_queue);
+}
+
+inline int api_queue::SaveQueueToPlaylist(wchar_t* playlist_file, int playlist_type)
+{
+ return _call(API_QUEUE_SAVEQUEUETOPLAYLIST, (int)0, playlist_file, playlist_type);
+}
+
+inline int api_queue::EnableQueueAdvance(int enabled)
+{
+ return _call(API_QUEUE_ENABLEQUEUEADVANCE, (int)0, enabled);
+}
+
+inline int api_queue::IsQueueAdvanceEnabled(void)
+{
+ return _call(API_QUEUE_ISQUEUEADVANCEENABLED, (int)0);
+}
+
+#endif
+
+// {7DC8C14F-F27F-48e8-A3D1-602BB3196E40}
+static const GUID QueueManagerApiGUID =
+{ 0x7dc8c14f, 0xf27f, 0x48e8, { 0xa3, 0xd1, 0x60, 0x2b, 0xb3, 0x19, 0x6e, 0x40 } };
+
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/Random/api_random.h b/Src/Agave/Random/api_random.h
new file mode 100644
index 00000000..d0618f16
--- /dev/null
+++ b/Src/Agave/Random/api_random.h
@@ -0,0 +1,78 @@
+#ifndef NULLSOFT_API_RANDOM_H
+#define NULLSOFT_API_RANDOM_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+
+typedef int (*RandomGenerator)(void);
+typedef unsigned long (*UnsignedRandomGenerator)(void);
+
+class api_random : public Dispatchable
+{
+protected:
+ api_random() {}
+ ~api_random() {}
+public:
+ RandomGenerator GetFunction();
+ UnsignedRandomGenerator GetUnsignedFunction();
+ int GetNumber();
+ int GetPositiveNumber();
+ float GetFloat(); // [0-1]
+ float GetFloat_LessThanOne(); // [0-1)
+ float GetFloat_LessThanOne_NotZero(); // (0-1)
+ double GetDouble(); // [0-1)
+public:
+ DISPATCH_CODES
+ {
+ API_RANDOM_GETFUNCTION = 10,
+ API_RANDOM_GETFUNCTION_UNSIGNED = 11,
+ API_RANDOM_GETNUMBER = 20,
+ API_RANDOM_GETPOSITIVENUMBER = 30,
+ API_RANDOM_GETFLOAT = 40,
+ API_RANDOM_GETFLOAT2 = 41,
+ API_RANDOM_GETFLOAT3 = 42,
+ API_RANDOM_GETDOUBLE = 50,
+ };
+};
+
+inline RandomGenerator api_random::GetFunction()
+{
+ return _call(API_RANDOM_GETFUNCTION, (RandomGenerator )0);
+}
+inline UnsignedRandomGenerator api_random::GetUnsignedFunction()
+{
+ return _call(API_RANDOM_GETFUNCTION_UNSIGNED, (UnsignedRandomGenerator )0);
+}
+
+inline int api_random::GetNumber()
+{
+ return _call(API_RANDOM_GETNUMBER, 0);
+}
+inline int api_random::GetPositiveNumber()
+{
+ return _call(API_RANDOM_GETPOSITIVENUMBER, 0);
+}
+inline float api_random::GetFloat()
+{
+ return _call(API_RANDOM_GETFLOAT, 0.f);
+}
+inline float api_random::GetFloat_LessThanOne()
+{
+ return _call(API_RANDOM_GETFLOAT2, 0.f);
+}
+inline float api_random::GetFloat_LessThanOne_NotZero()
+{
+ return _call(API_RANDOM_GETFLOAT3, 0.f);
+}
+inline double api_random::GetDouble()
+{
+ return _call(API_RANDOM_GETDOUBLE, 0.);
+}
+
+// {CB401CAB-CC10-48f7-ADB7-9D1D24B40E0C}
+static const GUID randomApiGUID =
+{ 0xcb401cab, 0xcc10, 0x48f7, { 0xad, 0xb7, 0x9d, 0x1d, 0x24, 0xb4, 0xe, 0xc } };
+
+
+#endif
+
diff --git a/Src/Agave/URIHandler/svc_urihandler.h b/Src/Agave/URIHandler/svc_urihandler.h
new file mode 100644
index 00000000..ed964e0e
--- /dev/null
+++ b/Src/Agave/URIHandler/svc_urihandler.h
@@ -0,0 +1,63 @@
+#pragma once
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include <bfc/std_mkncc.h> // for MKnCC()
+
+class svc_urihandler : public Dispatchable
+{
+protected:
+ svc_urihandler() {}
+ ~svc_urihandler() {}
+public:
+ static FOURCC getServiceType() { return svc_urihandler::SERVICETYPE; }
+ enum
+ {
+ NOT_HANDLED = -1, // return if it's not yours
+ HANDLED = 0, // return if it's yours, but other services might want to handle also
+ HANDLED_EXCLUSIVE = 1, // if it's yours AND NO ONE ELSES
+ };
+ int ProcessFilename(const wchar_t *filename);
+ int IsMine(const wchar_t *filename); // just like ProcessFilename but don't actually process
+ int EnumProtocols(size_t n, wchar_t *protocol, size_t protocolCch, wchar_t *description, size_t descriptionCch); // return 0 on success
+ int RegisterProtocol(const wchar_t *protocol, const wchar_t *winampexe);
+ int UnregisterProtocol(const wchar_t *protocol);
+
+ enum
+ {
+ PROCESSFILENAME=0,
+ ISMINE=1,
+ ENUMPROTOCOLS=2,
+ REGISTERPROTOCOL=3,
+ UNREGISTERPROTOCOL=4,
+ };
+
+ enum
+ {
+ SERVICETYPE = MK4CC('u','r','i', 'h')
+ };
+};
+
+inline int svc_urihandler::ProcessFilename(const wchar_t *filename)
+{
+ return _call(PROCESSFILENAME, (int)NOT_HANDLED, filename);
+}
+
+inline int svc_urihandler::IsMine(const wchar_t *filename)
+{
+ return _call(ISMINE, (int)NOT_HANDLED, filename);
+}
+
+inline int svc_urihandler::EnumProtocols(size_t n, wchar_t *protocol, size_t protocolCch, wchar_t *description, size_t descriptionCch)
+{
+ return _call(ENUMPROTOCOLS, (int)1, n, protocol, protocolCch, description, descriptionCch);
+}
+
+inline int svc_urihandler::RegisterProtocol(const wchar_t *protocol, const wchar_t *winampexe)
+{
+ return _call(REGISTERPROTOCOL, (int)1, protocol, winampexe);
+}
+
+ inline int svc_urihandler::UnregisterProtocol(const wchar_t *protocol)
+ {
+ return _call(UNREGISTERPROTOCOL, (int)1, protocol);
+ }