Дополнения программы (планы)

Модули, расширяющие возможности программы
Post Reply
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Дополнения программы (планы)

Post by Eugene »

В связи с появлением альтернативного редактора скриптов, возникла необходимость в организации работы с дополнениями в программе.

Планы:
  • Дополнения будут организованы в виде dll-модулей (экспортируемая функция HmsGetAddonList, для C# дополнений необходимо реализовать класс HmsAddonList).
  • Работа программы с дополнениями и дополнений с программой будет через интерфейсы.
Предполагаемые типы дополнений:
  • Дополнения, реализующие диалоговые функции (т.е. интерфейс с пользователем) - замена стандартных диалоговых окон или добавление кнопок, панелей в основную форму программы.
  • Дополнения, реализующие редактирование скриптов, поддерживаемых программой.
  • Дополнения, реализующие редактирование и выполнение произвольных скриптов.
  • Дополнения, расширяющие список функций встроенных скриптов.
  • Дополнения, предоставляющие ресурсы (видео, аудио, изображения) для использования в скриптах.
  • Дополнения, расширяющие список файлов, включаемых в базу медиа-ресурсов при сканировании каталогов медиа-ресурсов.
  • Дополнения, загружающие метаданные о медиа-ресурсах.
  • Дополнения, организующие хранение информации о медиа-ресурсах (база медиа-ресурсов).
  • Дополнения - обработчики http-запросов.
    ...
Большая часть перечисленных функций может быть выполнена и сейчас, но возможно дополнения будут более удобны для их разработчиков и пользователей.

:!: Нет планов по организации проверки, хранения, распространения дополнений, но лицензия программы разрешает сборку и распространение дистрибутивов программы с дополнительными файлами. :!:
[+] Особенности реализации Microsoft.NET дополнений
1. Вместе с файлом дополнения (например, MyHmsAddon.dll) должен идти ini-файл Windows, соответствующий названию модулю дополнения (для MyHmsAddon.dll файл должен называться MyHmsAddon.ini)

Code: Select all

[HmsAddonList]
Platform=Microsoft.NET
ClassName=HmsAddons.HmsAddonList
ClassName должен содержать полное название класса, реализующего интерфейс IHmsAddonList.

2. Вместе с файлом дополнения может быть конфигурационный файл Microsoft.NET (название MyHmsAddon.dll.config для MyHmsAddon.dll).
[+] Работа программы с дополнениями.
1. При сканировании каталога дополнений и его подкаталогов (по-умолчанию Каталог_установки_программы\Addons), программа обрабатывает dll-файлы.

2. Если есть ini-файл и платформа Microsoft.NET, то программа организует Microsoft.NET хост и загружает в него модуль дополнения,
создает объект, реализующий IHmsAddonList интерфейс.

3. Если нет ini-файла, то программа загружает dll-модуль (LoadLibrary) пытается получить (GetProcAddress) адрес экспортируемой функции
HmsGetAddonList, если функция HmsGetAddonList есть, то происходит ее вызов для получения интерфейса IHmsAddonList.

Code: Select all

 function HmsGetAddonList (out aAddonList: IHmsAddonList): HResult; stdcall;
4. После получения интерфейса IHmsAddonList, программа получает список (GetCount, GetAddonInfo) идентификаторов классов и интерфейсов,
которые они реализуют. Идентификаторы классов должны быть уникальными, но произвольными (т.е. программа не будет искать класс
с предопределенным идентификатором), идентификаторы интерфесов должны быть известны программе (например, для дополнения-редактора скриптов
идентификатор интерфейса '{B43BB779-379D-4244-A53D-0AAC3863A0FB}').

5. В дальнейшем программа использует IHmsAddonList.GetClassObject для создания объектов, реализующие функции дополнения.

6. IHmsAddonList.CanUnloadNow вызывается перед выгрузкой дополнения.
[+] Основной интерфейс дополнения - IHmsAddonList

Code: Select all

IHmsAddonList = interface(IDispatch)
  ['{A8F688A7-441E-4701-9EA0-9C591D0B997A}']
    function GetCount(var aCount: Integer): HResult; safecall;
    function GetAddonInfo(aIndex: Integer; var aClassID, aInterfaceID: TGUID;
        var aTitle, aDescription, aRequiredVersion, aCheckedOnVersion: OleVariant): HResult; safecall;
    function GetClassObject(const clsid: TGUID; const iid: TGUID; out pv: OleVariant): HResult; safecall;
    function CanUnloadNow: HResult; safecall;
  end;
[+] Предполагаемый интерфейс для дополнения - редактора скриптов.

Code: Select all


{ интерфейс редактора }

const
 { IHmsScriptEditor.GetCapabilities }
  ecEditor    = 1;
  ecStatusBar = 2;
  ecMessages  = 4;

type
  THmsScriptMode = (
    smUnknown = 0,
    smTranscoding,
    smWatchFoldersGroupName,
    smMediaInfo,
    smProcessMedia,
    smCreateFolderItems,
    smPodcastItemProperties,
    smMediaResourceLink,
    smWebMediaItems,
    smMimeType,
    smProcessMediaEvent,
    smCreatePodcastFeeds,
    smWebNavigation,
    smParsePlaylistFile,
    smAutoDetectDeviceType,
    smProcessMetadata,
    smDIDLLiteDescription,
    smHandleHTTPRequest); 

  IHmsScriptEditor = interface(IDispatch)
  ['{B43BB779-379D-4244-A53D-0AAC3863A0FB}']
    function AddMessage(const aMessage: OleVariant): HResult; safecall;

    function CreateEditor(aParent: THandle; const aHmsScripter: IHmsScriptFrame;
                   aScriptMode: Integer; var aEditor: THandle): HResult; safecall;

    function DestroyEditor(aEditor: THandle): HResult; safecall;

    function GetCapabilities(var aCapabilities: Integer): HResult; safecall;

    function GetCurrentLine(var aLine: Integer): HResult; safecall;

    function GetScriptName(var aScriptName: OleVariant): HResult; safecall;
    function GetScriptText(var aText: OleVariant): HResult; safecall;
    function SetScriptName(const aScriptName: OleVariant): HResult; safecall;
    function SetScriptText(const aText: OleVariant): HResult; safecall;

    function GetModified(var aModified: LongBool): HResult; safecall;

    function InvalidateLine(aLineIndex: Integer): HResult; safecall;

    function Repaint: HResult; safecall;

    function GetCaretPos(var aLine, aChar: Integer): HResult; safecall;
    function SetCaretPos(aLine, aChar: Integer): HResult; safecall;

    function SetFocus: HResult; safecall;

    function SetRunning(aValue: LongBool): HResult; safecall;

    function SetSelText(const aText: OleVariant): HResult; safecall;

    function Setup: HResult; safecall;
  end;
[+] Предполагаемый интерфейс программы, который предоставляется редактору

Code: Select all

const
{ IHmsScriptFrame.ProcessCommand }
  ecUserFirst       = 1001; 
  ecCompileScript    = ecUserFirst + 103;
  ecRunLine          = ecUserFirst + 100;
  ecRunScript        = ecUserFirst + 102;
  ecToggleBreakpoint = ecUserFirst + 101;
  ecEvaluate         = ecUserFirst + 104;
  ecWatches          = ecUserFirst + 105; 
type
  IHmsScriptFrame = interface(IDispatch)
  ['{D31B4638-9764-4A9A-9F5A-B4D0B519F402}']
    function AddWatch(const aExpression: OleVariant): HResult; safecall;

    function ChangeScriptName(const aScriptName: OleVariant): HResult; safecall;

    function CompileScript(const aScriptName, aScriptText: OleVariant; var aErrorMessage: OleVariant;
                           var aErrorLine, aErrorChar: Integer; var aResult: LongBool): HResult; safecall;

    function GenerateScriptDescriptions(var aXMLDescriptions: OleVariant): HResult; safecall;

    function GetCurrentState(var aRunning: LongBool;
                  var aCurrentSourceLine, aCurrentSourceChar: Integer): HResult; safecall;

    function IsBreakpointLine(aLine: Integer; var aResult: LongBool): HResult; safecall;
    function IsExecutableLine(aLine: Integer; var aResult: LongBool): HResult; safecall;

    function ProcessCommand(aCommand: Integer): HResult; safecall;

    function SolveExpression(const aExpression: OleVariant; var aResult: OleVariant): HResult; safecall;

    function ToggleBreakpoint(aLine: Integer): HResult; safecall;
  end;
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

Для вызова формы настройки дополнения и возможности обновления, добавлен интерфейс IHmsAddonTools, реализация необязательна, будет запрашиваться через IHmsAddonList.QueryInterface (т.е. у объекта, реализующего IHmsAddonList, можно добавить реализацию интерфейса IHmsAddonTools)
[+] Сервисный интерфейс дополнения

Code: Select all

{ 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;

Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

[+] Интерфейс для дополнения - панели в основную форму программы

Code: Select all

  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, если обработало данное действие.
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

[+] Интерфейс дополнений, расширяющих список функций встроенных скриптов

Code: Select all

  IHmsScriptFunctions = interface(IDispatch)
  ['{99546421-6D4B-4BEB-B778-285591F25D79}']
    function ExecuteFunction(const aFunctionName: OleVariant; var aFunctionParameters, aFunctionResult: OleVariant): HResult; safecall;
    function GetFunctionCount(var aCount: Integer): HResult; safecall;
    function GetFunctionInfo(aIndex: Integer; var aFunctionName, aFunctionDeclaration, aFunctionCategory, aFunctionDescription: OleVariant): HResult; safecall;
  end;

  Предопределенные значения для aFunctionCategory:
    ctConv - 'Преобразование'
    ctFormat - 'Форматирование'
    ctDate - 'Дата-время'
    ctString - 'Строковые'
    ctSystem - 'Системные'
    ctMath - 'Математические'
    ctOther - 'Другие'
    ctAggregate - 'Агрегатные'
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

[+] Интерфейс дополнений, реализующих диалоговые функции

Code: Select all

  IHmsFormProvider = interface(IDispatch)
  ['{6BC29D8C-77BD-48D2-A310-35C9F1374581}']
    function ShowModal(aOwner: THandle; const aFormClassName: OleVariant; var aParameters: OleVariant; var aModalResult: Integer): HResult; safecall;
  end;

  aParameters - массив именованных параметров (имя_параметра_1, значение_параметра_1, имя_параметра_2, значение_параметра_2, ..., имя_параметра_N, значение_параметра_N);
  Функция IHmsFormProvider.ShowModal должна вернуть S_OK, если дополнение обработало указанный класс форм.  

const
{ значения для aModalResult }
  idOK       = 1;
  idCancel   = 2;
  idAbort    = 3;
  idRetry    = 4;
  idIgnore   = 5;
  idYes      = 6;
  idNo       = 7;
  idClose    = 8;
  idHelp     = 9;
  idTryAgain = 10;
  idContinue = 11;
  mrNone     = 0;
  mrOk       = idOk;
  mrCancel   = idCancel;
  mrAbort    = idAbort;
  mrRetry    = idRetry;
  mrIgnore   = idIgnore;
  mrYes      = idYes;
  mrNo       = idNo;
  mrClose    = idClose;
  mrHelp     = idHelp;
  mrTryAgain = idTryAgain;
  mrContinue = idContinue;
  mrAll      = mrContinue + 1;
  mrNoToAll  = mrAll + 1;
  mrYesToAll = mrNoToAll + 1;
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

Для предоставления доступа к классам (объектам) программы добавлен добавлен интерфейс IHmsAddonInit, реализация необязательна, будет запрашиваться через IHmsAddonList.QueryInterface (т.е. у объекта, реализующего IHmsAddonList, можно добавить реализацию интерфейса IHmsAddonInit)
[+] Интерфейс для инициализации доступа к объектам программы

Code: Select all

type
  IHmsAddonInit = interface(IDispatch)
  ['{3AB5A0DB-190F-40AA-9FA3-88CC34432365}']
    procedure SetApplication(const aApplication: IHmsApplication); safecall;
  end;
После получения интерфейса IHmsAddonList программа запрашивает интерфейс IHmsAddonInit, если интерфейс получен, то программа вызывает IHmsAddonInit.SetApplication с ссылкой на интерфейс IHmsApplication
[+] Интерфейс для доступа объектам программы

Code: Select all

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 - выполнение скриптов программы

Code: Select all

  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.
[+] Интерфейс IHmsThumbnailsManager - доступ к эскизам медиа-ресурсов

Code: Select all

  IHmsThumbnailsManager = interface(IUnknown)
  ['{EFBB29E2-C170-4B33-ACAB-832F4443C070}']
    function AddThumbnail(const aThumbnailKey, aThumbnailFormat: OleVariant;
                          aThumbnailWidth, aThumbnailHeight: Integer;
                          const aThumbnailStream: IStream): LongBool; safecall;
    function CreateThumbnail(const aThumbnailKey: OleVariant; var aCreateParameters: OleVariant): LongBool; safecall;

    function GetThumbnail(const aThumbnailKey: OleVariant;
                          const aThumbnailStream: IStream): LongBool; safecall;
    function GetThumbnailInfo(const aThumbnailKey: OleVariant;
                              var aThumbnailFormat: OleVariant;
                              var aThumbnailWidth, aThumbnailHeight: Integer): LongBool; safecall;
    function ThumbnailExists(const aThumbnailKey: OleVariant): LongBool; safecall;
  end;
Eugene
Posts: 2805
Joined: Tue Sep 16, 2008 7:30 pm

Re: Дополнения программы (планы)

Post by Eugene »

Дополнительные интерфейсы для взаимодействия с дополнениями - провайдерами форм
[+] Интерфейс медиа-ресурса

Code: Select all

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.
[+] Интерфейс для перемещения по списку медиа-ресурсов

Code: Select all

  IHmsAddonMediaItemListNavigator = interface(IDispatch)
  ['{BAF6D656-D927-4A56-89FF-DF79C258D546}']
    procedure GotoBOF; safecall;
    procedure GotoPrev; safecall;
    procedure GotoNext; safecall;
    procedure GotoEOF; safecall;
    function IsBOF: LongBool; safecall;
    function IsEOF: LongBool; safecall;
    function IsTreeList: LongBool; safecall;
    function CurrentMediaItem: OleVariant; safecall;
  end;
Интерфейс передается в IHmsFormProvider.ShowModal с названием параметра Navigator.
Post Reply