Программирование на Delphi и не только » Архив блога Microsoft Agent. Часть II | Программирование на Delphi и не только

В прошлой части мы научились применять технологию Microsoft Agent в web-страничках. В этот раз мы будем работать с Delphi. Убедитесь, что установлены все необходимые компоненты (см. первую часть) и можно отправляться в увлекательное путешествие по миру MsAgent. Запустите Delphi и в меню «Component» выберите пункт «Import ActiveX Control…». В появившемся диалоговом окне нужно выделить строку «Microsoft Agent Control…» и нажать кнопку «Install». Далее произойдёт стандартный процесс установки нового компонента. После окончания инсталляции создайте новое приложение и поместите на форму полученный компонент – Agent1:TAgent (он должен находиться на закладке ActiveX).

Вот этот вот почти «ноль-ноль-семь» будет помогать нам создавать приложения, которые будут работать с технологией MsAgent. Начнём с небольшого примера, с маленького костяка, который можно будет использовать при разработке более сложных программ.

Установите свойству Connected компонента Agent1 значение True, затем объявите две глобальные переменные:

Var

  //для хранения персонажа   Character: IAgentCtlCharacterEx;

  //для получения состояния персонажа

  Request: IAgentCtlRequest;   Для события OnCreate формы запишите процедуру:
  procedure TForm1.FormCreate(Sender: TObject);
  begin
    //загружаем персонаж «Джин»     Request := Agent1.Characters.Load(‘genie’, ‘genie.acs’);

    //получаем объект персонажа Джин

    Character := Agent1.Characters.Character(‘genie’)as IAgentCtlCharacterEx;

    //Джин появляется

    Request := Character.Show(False);

    //Джин здоровается и вкратце рассказывает о себе

    Request := Character.Speak(‘Здравствуйте! ‘+Сharacter.Description, EmptyParam);

    //Джин играет анимацию «Greet»

    Request:=Character.Play(‘Greet’);

  end;

При закрытии формы нужно выгрузить персонаж:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin   Agent1.Characters.Unload(‘genie’);

end;

Если запустить эту программу, то вместе с формой появится Джин, который поздоровается и на несколько секунд застынет в приветственном поклоне. Теперь будем дополнять данный пример.
Как уже упоминалось в первой части, персонажи умеют проигрывать различные анимации, при этом для каждого персонажа могут определяться свои анимации. Поэтому иногда требуется получить все допустимые анимации для персонажа, что и делает следующая процедура: Procedure GetAgentAnim(st: TStrings);
var   AnEnum: IEnumVariant;   flag: Cardinal;   V: OleVariant;

begin

  //получаем интерфейс анимаций агента   AnEnum := (Character.AnimationNames.Enum) as IEnumVariant;

  //Сбрасываем указатель списка на начало

  AnEnum.Reset;

  //перебираем все анимации и добавляем их в наш список

  repeat     AnEnum.Next(1, V, flag);

    if (VarToStr(V) ») then

      st.Add(V);

  until (flag = 0);

end; Давайте проверим работоспособность данной процедуры. Добавьте на форму кнопку Button1 и список ListBox1. Дайте заголовок кнопке «Список анимаций» и запишите процедуру обработки её нажатия: procedure TForm1.Button1Click(Sender: TObject);
begin   GetAgentAnim(ListBox1.Items);

end;

Данная процедура записывает список анимаций загруженного персонажа в компонент ListBox1. А теперь сделаем так, чтобы при двойном щелчке мышкой по ListBox’у Джин проигрывал выбранную анимацию:

procedure TForm1.ListBox1DblClick(Sender: TObject);
begin   Request := Character.Play(ListBox1.Items[ListBox1.ItemIndex]);

end;

Теперь посмотрим, зачем нам переменная Request (её мы объявили как глобальную). Именно она служит для синхронизации действий персонажа (либо персонажей, если их несколько). Интерфейс IAgentCtlRequest имеет одно очень полезное свойство – Status. В зависимости от состояния запроса, который в данный момент выполняет персонаж, это свойство принимает следующие значения:

Status | Пояснения   0             Запрос успешно выполнен   1             Запрос «провалился»   2             Запрос не выполняется, т.к. ждёт завершения обработки других запросов   3             Запрос прерван

  4             Запрос обрабатывается

На основе этой таблички легко написать процедуру, которая будет дожидаться выполнения всех запросов к персонажу, а затем вернёт программе управление:

procedure WaitFor(Request:IAgentCtlRequest);
begin
  repeat     Application.ProcessMessages;     Status := Request.Status;

  until (Request.Status 2) and (Request.Status 4);

end;

Для примера добавьте на форму кнопку «Пример WaitFor»:

procedure TForm1.Button3Click(Sender: TObject);
begin
  //Джин произносит фразу   Request := Character.Speak(‘Доброе утро’, EmptyParam);

  {waitfor(Request);}

  //Показываем сообщение   ShowMessage(‘Всё’);

end;

Если нажать на кнопку, то Джин начнёт говорить и сразу же появится сообщение. А если снять комментарии со строки waitfor(Request);, то сообщение появится только после того, как Джин закончит говорить. А сейчас «научим» Джина вслух произносить текущее время. Для этого ему нельзя подсунуть строку типа «21 час 44 минуты 32 секунды», эту строку он произнесёт так: «двадцать один час, сорок четвёртого минуты, тридцать второго секунды». В связи с этим, Джину нужно полностью «разжевать», что именно он должен произносить. Так что будем давать ему такую строку: «21 час, 44 минуты, 30 две секунды». Т.е. число, стоящее в женском роде (32 секунды), разделяем на составляющие (30 две секунды).

Добавьте на форму очередную кнопку «Сколько времени?» и запишите следующую процедуру:

procedure TForm1.Button1Click(Sender: TObject);
var   buf, str: string;   Hour, Min, Sec, Msec: Word;   Hours, Mins, Secs: string;   hs, ms, ss: string;   DT: TDateTime;

begin

  hs := »;   ms := »;   ss := »;

  //узнаём текущее время

  DT := Now;

  //разбиваем его на составляющие

  DecodeTime(DT, Hour, Min, Sec, MSec);

  //смотрим, какое окончание должно быть у слова «час»

  case hour of     2..4, 22, 23: hs := ‘а’;     0, 5..20: hs := ‘ов’;

  end;

  //окончание слова «минута»
  case min of     1, 21, 31, 41, 51: ms := ‘а’;     2..4, 22..24, 32..34, 42..44, 52..54: ms := ‘ы’;

  end;

  //окончание слова «секунда»
  case sec of     1, 21, 31, 41, 51: ss := ‘а’;     2..4, 22..24, 32..34, 42..44, 52..54: ss := ‘ы’;

  end;

  //часы не будем преобразовывать, т.к. слово «час» мужского рода   hours := inttostr(hour);

  //при необходимости разбиваем минуты на слова

  mins := inttostr(min);

  if (mins[length(mins)] = ‘1’) and (min 11) then

  begin
    if (min > 10) then buf := mins[1] + ‘0 ‘
    else buf:=»;     mins := buf + ‘одна’;

  end

  else
  begin
    if (mins[length(mins)]=’2′) and (min12) then
    begin
      if (min>10) then buf:=mins[1]+’0 ‘
      else buf:=»;       mins := buf + ‘две’;

    end
  end
;

  //при необходимости разбиваем секунды на слова   secs := inttostr(sec);

  if (secs[length(secs)]=’1′) and (sec11) then

  begin
    if (sec>10) then buf := secs[1] + ‘0 ‘
    else buf := »;     secs := buf + ‘одна’;

  end

  else
  begin
    if (secs[length(secs)]=’2′) and(sec12) then
    begin
      if (sec>10) then buf := secs[1] + ‘0 ‘
      else buf:=»;       secs := buf + ‘две’;

    end;

  end;
  //составляем строку, которую должен произнести Джин   str := hours + ‘ час’ + hs+ ‘, ‘ + mins + ‘ минут’ + ms + ‘, ‘ + secs + ‘ секунд’ + ss;

  //Джин произносит строку str, а над ним отображается текущее время (рис.1)

  Request := Character.Speak(‘\Pit=18400\\Spd=100\\Map=»‘+str+'»=»‘+timetostr(DT)+'»\’,EmptyParam);

end;

Напоследок рассмотрим некоторые параметры голосового движка. На один компьютер можно установить поддержку нескольких языков. Чтобы переключаться между ними, нужно изменять параметр персонажа LanguageID. В таблице приведены идентификаторы к некоторым языкам. Символ «$» означает, что число представлено в шестнадцатеричной системе счисления.               

Пример: Character.LanguageID := $409; – переключаемся на английский язык. Ещё можно изменять сам голос. Для этого есть свойство TTSModeID. Ниже приведён список голосов для русского и английского языков.

Пример:

Сharacter.TTSModeID:='{06377F80-D48E-11d1-B17B-0020AFED142E}’;

устанавливает женский голос для русского языка. Так что можете поиздеваться над Джином, заставляя его разговаривать женским голосом.

На сегодня всё, в следующей части мы научимся управлять Джином при помощи голосовых команд.


Иван Ширко

ishyrko@gmail.com