В связи с появлением альтернативного редактора скриптов, возникла необходимость в организации работы с дополнениями в программе.
Планы:
Дополнения будут организованы в виде dll-модулей (экспортируемая функция HmsGetAddonList, для C# дополнений необходимо реализовать класс HmsAddonList).
Работа программы с дополнениями и дополнений с программой будет через интерфейсы.
Предполагаемые типы дополнений:
Дополнения, реализующие диалоговые функции (т.е. интерфейс с пользователем) - замена стандартных диалоговых окон или добавление кнопок, панелей в основную форму программы.
Дополнения, реализующие редактирование и выполнение произвольных скриптов.
Дополнения, расширяющие список функций встроенных скриптов.
Дополнения, предоставляющие ресурсы (видео, аудио, изображения) для использования в скриптах.
Дополнения, расширяющие список файлов, включаемых в базу медиа-ресурсов при сканировании каталогов медиа-ресурсов.
Дополнения, загружающие метаданные о медиа-ресурсах.
Дополнения, организующие хранение информации о медиа-ресурсах (база медиа-ресурсов).
Дополнения - обработчики http-запросов.
...
Большая часть перечисленных функций может быть выполнена и сейчас, но возможно дополнения будут более удобны для их разработчиков и пользователей.
Нет планов по организации проверки, хранения, распространения дополнений, но лицензия программы разрешает сборку и распространение дистрибутивов программы с дополнительными файлами.
1. Вместе с файлом дополнения (например, MyHmsAddon.dll) должен идти ini-файл Windows, соответствующий названию модулю дополнения (для MyHmsAddon.dll файл должен называться MyHmsAddon.ini)
1. При сканировании каталога дополнений и его подкаталогов (по-умолчанию Каталог_установки_программы\Addons), программа обрабатывает dll-файлы.
2. Если есть ini-файл и платформа Microsoft.NET, то программа организует Microsoft.NET хост и загружает в него модуль дополнения,
создает объект, реализующий IHmsAddonList интерфейс.
3. Если нет ini-файла, то программа загружает dll-модуль (LoadLibrary) пытается получить (GetProcAddress) адрес экспортируемой функции
HmsGetAddonList, если функция HmsGetAddonList есть, то происходит ее вызов для получения интерфейса IHmsAddonList.
function HmsGetAddonList (out aAddonList: IHmsAddonList): HResult; stdcall;
4. После получения интерфейса IHmsAddonList, программа получает список (GetCount, GetAddonInfo) идентификаторов классов и интерфейсов,
которые они реализуют. Идентификаторы классов должны быть уникальными, но произвольными (т.е. программа не будет искать класс
с предопределенным идентификатором), идентификаторы интерфесов должны быть известны программе (например, для дополнения-редактора скриптов
идентификатор интерфейса '{B43BB779-379D-4244-A53D-0AAC3863A0FB}').
5. В дальнейшем программа использует IHmsAddonList.GetClassObject для создания объектов, реализующие функции дополнения.
6. IHmsAddonList.CanUnloadNow вызывается перед выгрузкой дополнения.
Для вызова формы настройки дополнения и возможности обновления, добавлен интерфейс IHmsAddonTools, реализация необязательна, будет запрашиваться через IHmsAddonList.QueryInterface (т.е. у объекта, реализующего IHmsAddonList, можно добавить реализацию интерфейса IHmsAddonTools)
{ IHmsAddonTools.Update flags }
ufCheckExistsOnly = $01; // проверить существование обновления (in)
ufIsHttpLink = $02; // результат - http-ссылка на zip-файл дополнения (out)
ufIsLocalFile = $04; // результат - скаченный zip-файл дополнения (out)
ufIsInfoMessage = $08; // результат - информационное сообщение (например, что обновление прошло успешно) (out)
ufIsErrorMessage = $10; // результат - сообщение об ошибке (out)
ufIsWarningMessage = $20; // результат - сообщение, требующее внимания (например, что требуется перезагрузка программы) (out)
type
IHmsAddonTools = interface(IDispatch)
['{C5B24BFB-1F30-4F8A-91AD-943B82D8A067}']
function Setup(aOwner: THandle; var aReload: LongBool): HResult; safecall;
function Update(var aFlags: Integer; var aResult: OleVariant): HResult; safecall;
end;
IHmsMainFormControl = interface(IDispatch)
['{6E86502E-15BC-4358-A4A1-29D97CDEF073}']
function CreateControl(aParent: THandle; const aReserved: IUnknown; var aControl: THandle): HResult; safecall;
function DestroyControl(aControl: THandle): HResult; safecall;
function GetCaption(var aCaption: OleVariant): HResult; safecall;
function SetFocus: HResult; safecall;
function ExecuteAction(const aActionName: OleVariant; const aActionParameters: OleVariant): HResult; safecall;
function GetActionCount(var aCount: Integer): HResult; safecall;
function GetActionInfo(aIndex: Integer; var aActionName, aActionTitle, aActionDescription: OleVariant): HResult; safecall;
end;
Возможные реализации - проигрыватели медиа-файлов в главной форме программы, загрузчики медиа-файлов, просмотр интернета с использованием "Воспроизвести на...".
В версии 2.04 добавлен вызов IHmsMainFormControl.ExecuteAction с aActionName = 'open' при выборе в главной форме программы "Открыть файл". Дополнение должно вернуть S_OK, если обработало данное действие.
Для предоставления доступа к классам (объектам) программы добавлен добавлен интерфейс IHmsAddonInit, реализация необязательна, будет запрашиваться через IHmsAddonList.QueryInterface (т.е. у объекта, реализующего IHmsAddonList, можно добавить реализацию интерфейса IHmsAddonInit)
После получения интерфейса IHmsAddonList программа запрашивает интерфейс IHmsAddonInit, если интерфейс получен, то программа вызывает IHmsAddonInit.SetApplication с ссылкой на интерфейс IHmsApplication
type
IHmsApplication = interface(IBaseInterface)
['{99C4E03E-8044-4431-A53D-B9E999884B2E}']
function GetInterface(const aInterfaceID: TGUID; out aObject: OleVariant): HResult; safecall;
end;
После получения интерфейса IHmsApplication, дополнение может получить доступ к различным классам (объектам) программы через вызов IHmsApplication.GetInterface, на данный момент реализован запрос интерфейсов IHmsScripter - выполнение скриптов программы, IHmsThumbnailsManager - доступ к эскизам медиа-ресурсов.
IHmsScripter = interface(IDispatch)
['{786039DF-E1B1-466C-AF74-A6B1DAB2F8AE}']
function CreateScript(const aClientInfo: OleVariant; aScriptMode: Integer): LongBool; safecall;
function CompileScript(const aScriptName, aScriptText: OleVariant;
var aErrorMessage: OleVariant; var aErrorLine, aErrorChar: Integer): LongBool; safecall;
function ExecuteScript(const aInParameters: OleVariant; var aOutParameters: OleVariant): LongBool; safecall;
end;
aInParameters, aOutParameters - массив именованных параметров (имя_параметра_1, значение_параметра_1, имя_параметра_2, значение_параметра_2, ..., имя_параметра_N, значение_параметра_N); перед выполнением скрипта программа устанавливает значения переменных в aInParameters, после выполнения устанавливает значения переменных в aOutParameters.
type
IHmsAddonMediaItem = interface(IDispatch)
['{097D84B0-B557-4C03-BDEE-0D6E9E405DE5}']
function GetProperties(const aIndexOrName: OleVariant): OleVariant; safecall;
procedure SetProperties(const aIndexOrName, aPropertyValue: OleVariant); safecall;
function ExecuteMethod(const aMethodName: OleVariant; var aMethodParameters: OleVariant): OleVariant; safecall;
function PropertyExists(const aIndexOrName: OleVariant): LongBool; safecall;
property Properties[const aIndexOrName: OleVariant]: OleVariant read GetProperties write SetProperties; default;
end;
Идентификаторы свойств из скриптов или
'FolderOrigin' - папка-источник для ссылок (IHmsAddonMediaItem)
'FolderSortOrder' - сортировка папки
'FolderType' - тип папки (ftDefaultFolder = 0, ftDynamicFolder, ftTranscodingFolder, ftGroupByFolder, ftPodcastSubFolder, ftDeviceDynamicFolde)
'HideItem' - скрытый медиа-ресурс
'IsArchiveItem' - медиа-ресурс из архива
'IsBdItem' - медиа-ресурс из Bluray-структуры
'IsCueFileItem' - медиа-ресурс из CueSheet
'IsDvbItem' - медиа-ресурс цифрового телевидения
'IsDvdItem' - медиа-ресурс из DVD-структуры
'IsDirectLink' - если True, то на устройство передается оригинальная ссылка на медиа-ресурс
'IsFolder' - True, если элемент является папкой
'IsInternetItem' - True, если элемент в папке Интернет-телевидения или Интернет-радио
'IsInternetRadio' - True, если элемент в папке Интернет-радио
'IsIsoItem' - медиа-ресурс из образа диска
'IsLink' - элемент является ссылкой
'IsMixedItem' - медиа-ресурс в структуре "Каждый фильм в отдельной папке"
'IsOriginalLink' - ссылка на медиа-ресурс в папке Оригинал
'IsPodcast' - элемент в папке подкастов
'IsStreamItem' - IsDvbItem или IsInternetItem или IsPodcast
'IsTempItem' - элемент, который не сохраняется в базе данных (Транскодирование, Динамические папки, Сервисные папки)
'IsUrlItem' - IsInternetItem или путь содержит ://
'IsVirtualVideo' элемент в папке Музыка (Визуализация) или Фото (Слайд-шоу)
'IsWebShot' - путь элемента начинается с webshot:// (снимок Web-страницы)
'ItemBookmarkPath' - путь элемента для закладки
'ItemDate' - дата медиа-ресурса
'ItemExists' - True, есди элемент из архива или файл существует
'ItemID' - идентификатор медиа-ресурса
'ItemIDPath' - путь медиа-ресурса от корня
'ItemImageIndex' - индекс иконки медиа-ресурса
'ItemImagePath' - название файла иконки медиа-ресурса для Web-навигации
'ItemIsoURL' - путь медиа-ресурса в образе диска
'ItemOrigin' - элемент-источник для ссылок (IHmsAddonMediaItem)
'ItemParent' - родительский элемент (IHmsAddonMediaItem)
'ItemPath' - путь элемента (путь файл, интернет-ссылка)
'ItemRotate' - поворот фотографии
'ItemSafeID' - ItemID для сохраняемых элементов, ItemIDPath - для временных элементов
'ItemSize' - размер медиа-ресурса в байтах
'ItemState' - состояние элемента
'ItemTimeLength' - длительность медиа-ресурса
'ItemTitle' - название медиа-ресурса
'MediaResourceSource' - путь медиа-ресурса для транскодирования
'MediaType' - тип медиа-ресурса (mtUnknown, mtAudio, mtImage, mtVideo, mtText, mtIsoDisk, mtCueSheet, mtPlaylist)
'OriginalPath' - путь, сохраненный в базе данных
'RatingsOrigin' - элемент-источник для родительского контроля
'RootItem' - корневой элемент
'ShortItemID' - сокращенный (16 символов) идентификатор элемента
'Transcoding' - True, если элемент в папке Транскодирования или Виртуального видео
'Thumbnail' - эскиз медиа-ресурса
'ThumbnailExists' - True, если эскиз существует или потенциально (видео, фото) существует
'ThumbnailFileName' - имя файла эскиза
'ThumbnailKey' - ключ эскиза в базе эскизов
'ThumbnailOrigin' - элемент-источник для эскиза (IHmsAddonMediaItem)
Интерфейс передается в IHmsFormProvider.ShowModal с названием параметра MediaItem.