<para>Важным составляющим &MCOP; является <emphasis>язык описания интерфейса</emphasis> &IDL;, с помощью которого описано большинство интерфейсов &arts; и <acronym>API</acronym>. </para>
<para>Чтобы использовать &IDL;, интерфейсы из C++ компилируются &IDL;-компилятором вместе с кодом C++. При реализации интерфейса вы наследуете от базового класса &IDL;, созданного компилятором. При использовании интерфейсов это можно сделать с помощью надстраивания функциональности. Таким образом, &MCOP; может пользоваться своим протоколом, даже если объект нелокален. Так вы получаете прозраночть работы в сети. </para>
<para>В этой главе описываются основные черты объектной модели, получаемой при использовании &MCOP;, сам протокол и его использование в C++ (связывание языков) и т.д. </para>
<para>Большинство сервисов &arts; (к примеру, модули и звуковой сервер) определены в терминах <acronym>интерфейсов</acronym>. А интерфейсы описаны в формате, не зависящем от языка: &IDL;. </para>
<para>Таким образом, многие детали вроде формата потоков медиаданных, прозрачность сети и зависимости от языка программирования можно скрыть в описании интерфейса. Инструмент &mcopidl; преобразовывает определение интерфейса для конкретного языка программирования (сейчас поддерживается только C++). </para>
<para>Интерфейсы в &IDL; - это почти то же самое, что класс в C++ или структура в C, но с некоторыми ограничениями. Как и в C++, интерфейсы наследовать от других интерфейсов. В определение интерфейса можно включать: потоки, атрибуты и методы. </para>
<para>Направленность потоков зависит от квалификатора (выход или вход). Аргумент типа определяет тип данных (один из перечисленных ниже типов атрибутов), однако поддерживаются ещё не все типы. Во многих модулях типом потока ставится аудио, это внутренний формат данных. Несколько потоков одного типа могут быть объявлены через запятую. </para>
<para>По умолчанию потоки синхронны, т.е. передача данных идёт постоянно и на определённой частоте, как <acronym>PCM</acronym>-аудио. Если вы установите параметр async, поток будет асинхронным, т.е. данные будут передаваться с перерывами. Примером асинхронных потоков могут служить &MIDI;-сообщения. </para>
<para>Ключевое слово multi, допустимое только для входных потоков, указывает на то, что поток может принимать переменное количество входов. Это удобно при создании таких устройств, как микшеры, которые могут принимать любое количество входных потоков. </para>
<para>Атрибуты - это данные, ассоциирующиеся с объектом интерфейса. Они определяются как переменные-члены классов в C++ и могут быть одного из простейших типов данных: boolean, byte, long, string или float - а такжеструктурами, определёнными пользователем, перечисляемого типа (enum) или последовательностью с переменной длиной (используется <type>). Лучше всего атрибуты помечать как доступные только для чтения. </para>
<para>Как и в C++, методы могут определяться в интерфейсах. Тип параметров метода может быть таким же, у атрибута. Ключевое слово oneway показывает, что метод возвращает какое-то значение сразу и выполняется асинхронно. </para>
<para>В &arts; уже определены несколько стандартных модульных интерфейсов, например, <interfacename>StereoEffect</interfacename> и <interfacename>SimpleSoundServer</interfacename>. </para>
<para>Простым примером модуля &arts; может служить модуль постоянных задержек из файла <filename>tdemultimedia/arts/modules/artsmodules.idl</filename>. Определение интерфейса приведено ниже. </para>
<para>Модуль наследует от <interfacename>SynthModule</interfacename>. Этот интерфейс, описанный в <filename>artsflow.idl</filename>, определяет методы, использующиеся во всех модулях-синтезаторах. </para>
<para>Эффект CDELAY задерживает звуковой стереопоток на время, указанное как параметр с плавающей точкой. В определении интерфейса есть атрибут типа float для хранения длительности задержки. Он определяет два входных аудиопотока и два выходных. Никаких других методов, кроме тех, от которых он наследует, не требуется. </para>
<para>Первый случай очень прост: получив 200 сэмплов на входе, модуль воспроизводит 200 сэмплов на выходе. Т.е. выходные данные производятся только после получения входных. </para>
<para>Во втором случае при 200 входных сэмплов производится другое число выходных. Это зависит от выполненного преобразования, но их количество известно заранее. </para>
<para>В третьем случае всё ещё сложнее. Нельзя угадать заранее, сколько байтов будет сгенерировано из 200 сэмплов (возможно, гораздо больше, но...). </para>
<para>В &arts;-0.3.4 поддерживались потоки только первого типа, и большинство задач выполнялись. Возможно, это и требуется при написании модулей обработки аудиоданных. Со сложными типами потоков возникают проблемы, т.к. их очень сложно программировать и большая часть функций часто не нужна. Поэтому мы решили использовать два типа потоков: синхронные и асинхронные. </para>
<para>Функция <function>calculateBlock()</function> будет вызываться в том случае, если есть достаточное количество входных данных и указатели содержат ссылки на данные. </para>
<para>Модули могут формировать данные время от времени, с меняющейся частотой модуляции или только если они не ограничены правилом <quote>на запрос любой длины нужно отвечать</quote>. </para>
<para>Исходящие потоки: содержат открытые функции для размещения пакетов, пересылки и учёта данных (используя этот механизм, вы будете знать, когда следует передать очередную порцию данных). </para>
<para>Входящие потоки: вызов происходит при получении нового пакета, вам нужно послать ответ, когда он будет обработан (вы можете послать сообщение об этом позже, если пакет кем-нибудь обработан, он будет освобождён/использовано заново). </para>
<para>В определении потоков используется ключевое слово <quote>async</quote> для указания асинхронного потока. Если вы, к примеру, решили преобразовать ваш асинхронный поток байтов в синхронный поток сэмплов, интерфейс должен выглядеть так: </para>
<para>Как посылать данные? Первый способ называется <quote>принудительная доставка</quote>. В асинхронных потоках данные посылаются пакетами. Это значит, что вы посылаете отдельные пакеты байтов, как в примере выше. Вся процедура состоит в том, чтобы разместить пакет, заполнить его и послать. </para>
<para>Как видите, это достаточно просто. Но если пакеты нужно посылать с такой скоростью, чтобы получатель успевал их обрабатывать, нужен другой подход - <quote>доставка с задержкой</quote>. Сначала вы посылаете какое-то количество пакетов, в то время, когда получатель по очереди их обрабатывает, формируете новые и опять посылаете их. </para>
<para>Мы обсудили, как отправлять данные. Получать их намного проще. Предположим, есть простой фильтр ToLower, который преобразовывает все буквы в нижний регистр: </para>
<para>Как видите, при получении пакета вызывается функция (в нашем случае это <function>process_indata</function>). А чтобы показать, что пакет обработан, нужно вызвать метод <methodname>processed()</methodname>. </para>
<para>Совет по использованию: если обработка проходит медленно (к примеру, если нужно ждать вывода данных звуковой картой), не вызывайте processed() сразу же, а только после того, как пакет будет действительно обработан. Тогда отправитель будет знать, сколько времени требуется на самом деле. </para>
<para>Предположим, есть 2 объекта, например, AudioProducer и AudioConsumer. У AudioProducer есть выходной поток, ау AudioConsumer - входной. Соединяя их, вы будете использовать эти потоки. С помощью стандартных потоков соединение упрощается: не нужно указывать порты. </para>
<para>Пусть теперь у нас есть объекты стререозвука, у каждого есть <quote>левый </quote> и <quote>правый</quote> порт. Очень хочется, чтобы подключение было как можно проще. Но как система узнает, какие порты соединять? Тут опять помогут стандартные потоки: можно указать несколько потоков по порядку. Поэтому, когда вы будете подключать два выходных стандартных потока к двум входным, не нужно будет указывать порты, а соответствие будет правильным. </para>
<para>Конечно, это не ограничено стреозвуком. Любое количество потоков можно сделать стандартным при необходимости, а функция связи будет проверять совпадение количества стандартных потоков двух объектов (в необходимом направлении), если вы не укажете порты. </para>
<para>В этом примере у объекта два входных порта будут соединены по умолчанию. Порядок определяется по строке со словом default. Поэтому у такого объекта: </para>
<para>Соединение <quote>couic</quote> с <quote>input1</quote> и <quote>bzzt</quote> с <quote>input2</quote> будет установлено автоматически. Заметьте, что в этом случае единственный выходной порт будет стандартным (смотрите ниже). Синтаксис генератора шума удобен для описания другого порядка или выбора только некоторых портов по умолчанию. Направления портов будет назначать &mcopidl;, поэтому не указывайте их. Входные и выходные порты можно записать в одной строке, важен лишь порядок. </para>
<para>Если в &IDL; указан стандартный список, пользуйтесь им. В него могут быть добавлены родительские порты, независимо от того, были ли они стандартными. </para>
<para>Иначе наследоваться будут родительские порты по умолчанию в таком порядке: родитель1 порт1, родитель1 порт2, ..., родитель2 порт1, ... Если есть общий предок с двумя родительскими ветвями, по умолчанию использоваться будет первый попавшийся в списке порт. </para>
<para>Флаги смены атрибута - это способ показать, что атрибут изменился. Они похожи на сигналы и функции внешнего вызова в &Qt; или Gtk. Например, если есть элемент &GUI; ползунок, отмечающий значение от 0 до 100, то должен быть объект, работающий с этим значением (к примеру, он может управлять громкостью сигнала). Будет удобно, если объект будет знать, изменился ли уровень громкости. Связь между отправителем и получателем. </para>
<para>В &MCOP; есть возможность контролировать изменения атрибутов. Независимо от того, что объявлено в &IDL;, <quote>атрибут</quote> может (и должен) изменяться, а также получать сообщения об изменении. Например, если у вас было два &IDL;-интерфейса: </para>
<para>Как видите, у каждого атрибута есть два разных потока: для отправки извещений об изменении вызывается <function><replaceable>имя атрибута</replaceable> _changed</function> и для получения — <function>attributename</function>. </para>
<para>Важно знать, что флаги изменения совместимы с асинхронными потоками. А также они "прозрачны", поэтому вы можете связать атрибут типа float элемента &GUI; с асинхронным потоком модуля синтезатора на другом компьютере. Естественно, изменение флага <emphasis>не будет синхронным </emphasis>, т. к. на передачу уходит некоторое время. </para>
<para>Если вы используете объекты с атрибутами, извещение об изменении нужно посылать каждый раз, когда атрибут меняется. Код выглядит приблизительно так: </para>
<para>Мы рекомендуем такой код для всех создаваемых объектов, чтобы флаги изменения могли использовать другие люди. Однако не стоит посылать извещения слишком часто, поэтому если вы обрабатываете сигнал, будет удобно записывать, когда было послано последнее извещение, чтобы не посылать егос каждым сэмплом. </para>
<para>Будет особенно полезно менять флаг вместе с оболочками (которые, к примеру, визуализируют аудио данные), элементами gui, контроля и мониторинга. Такой код находится в <filename class="directory">tdelibs/arts/tests</filename> а экспериментальая реализация artsgui - в <filename class="directory">tdemultimedia/arts/gui</filename>. </para>
<para>Файл <literal role="extension">.mcoprc</literal> (в каталоге home каждого пользователя) может быть использован для настройки &MCOP;. Сейчас возможно следущее: </para>
<para>Имя интерфейса для глобальной связи. Глобальная связь необходима для того, чтобы находить другие объекты и получать личные данные пользователя. Для разных &MCOP;-клиентов/серверов, которые должны быть как-то связаны, нужен общий объект GlobalComm для разделения информации между ними. Возможные значения: <quote>Arts::TmpGlobalComm</quote> для связи посредством каталога <filename class="directory">/tmp/mcop-<replaceable>имя пользователя</replaceable></filename> (который будет только на локальном компьютере) и <quote>Arts::X11GlobalComm</quote> для связи через свойства корневого окна сервера X11. </para>
<title>&MCOP; для пользователей <acronym>CORBA</acronym></title>
<para>Если вы пользовались <acronym>CORBA</acronym> раньше, вы заметите, что &MCOP; очень похож на эту технологию. Вообще-то до версии 0.4 &arts; использовал <acronym>CORBA</acronym>. </para>
<para>Основная идея <acronym>CORBA</acronym> такая же: вы создаёте объекты (компоненты). В &MCOP; ваши объекты доступны как обычные классы, в том числе и для удалённого сервера. Для этого нужно определить интерфейс объектов в файле &IDL;, так же, как и в <acronym>CORBA</acronym>. Однако есть несколько различий. </para>
<title>Функции <acronym>CORBA</acronym>, которые отсутствуют в &MCOP;</title>
<para>В &MCOP; нет параметров <quote>вход</quote> и <quote>выход</quote> вызова методов. Параматры всегда входящие, а возвращаемый код всегда исходящий. Это значит, что интерфейс: </para>
<title>Функции <acronym>CORBA</acronym>, отличающиеся в &MCOP;</title>
<para>В &MCOP; последовательности определяются так: <quote>последовательность<replaceable>тип</replaceable></quote>. Нет необходимости писать typedef. Например, вместо </para>
<para>Это значит, что ваш объект будет принимать два входящих синхронных аудиопотока signal1 и signal2. "Синхронный" значит, что эти потоки обязательно будут выдавать определённое количество данных. Т. е. если вызывается ваш объект и ему передаётся 200 сэмплов (signal1 + signal2), он выдаст 200 сэмплов. </para>
<para>Для работы со строками используется класс C++ <acronym>STL</acronym> <classname>string</classname>. Если они хранятся в последовательности, они хранятся <quote>просто тпе</quote>, т.е. они считаются простым типом. Поэтому им необходимо копирование. </para>
<para>Все структуры созданы из класса &MCOP; <classname>Type</classname> и сгенерированы компилятором &IDL;. Если они хранятся в массиве, для того, чтобы избежать копирования, хранятся только ссылки. </para>
<para>Вы компилируете его, вызвав <userinput><command>mcopidl</command> <parameter>hello.idl</parameter></userinput>, при этом сгенерируется <filename>hello.cc</filename> и <filename>hello.h</filename>. Чтобы эти файлы использовать, нужно определить C++ класс, который будет наследовать каркас: </para>
<programlisting>//заголовочный файл C++ - hello.h - включается ранее
<para>Так как передача данных между серверами &MCOP; идёт по протоколу <acronym>TCP</acronym>, любой (если вы подключены к Интернету) может попробовать подключиться к сервисам &MCOP;. Поэтому рекомендуется использовать аутентификацию клиентов. В &MCOP; используется протокол md5-auth </para>
<para>При каждом подключении клиента проверяется, знает ли он секретный пароль, при этом пароль не пересылается по сети, чтобы любой, прослушивающий сеть, не мог его получить. </para>
<para>Чтобы назначить каждому клиенту свой секретный пароль, &MCOP; запишет его в каталоге <filename class="directory">mcop</filename> (<filename class="directory">/tmp/mcop-<envar>USER</envar>/secret-cookie</filename>). Конечно, вы можете его скопировать на другой компьютер. Однако в этом случае нужен безопасный способ копирования, например, <command>scp</command> (из <application>ssh</application>). </para>
<para>Алгоритм искажения MD5 не позволяет восстановить <quote>исходный текст</quote>, т.е. секретный S и случайный R пароли (который все знают) из преобразованного пароля M. </para>
<para>Пока не завершится этап аутентификации, никаких других сообщений сервер принимать не будет. Например, если он ожидает сообщение <quote>ClientHello</quote>, а получает mcopInvocation, связь разрывается. </para>
<para>Если клиент пытается послать слишком большое сообщение (4096 байтов во время аутентификации), оно обрезается до 0 байтов, и сервер считает, что сообщение не было послано. Это необходимо, чтобы неаутентифицированный пользователь не мог послать сообщение в 100 мегабайт и израсходовал всю память сервера. </para>
<para>Вы можете создать объектную мультимедиа-модель, которую можно будет использовать для связи между компонентами в одном адресном пространстве (в одной задаче), а также между компонентами в различных потоках, задачах и на разных узлах. </para>
<para>Он будет доработан, чтобы выполнение проходило очень быстро и подходило "общительным" приложениям. Например, потоки видео - одно из приложений &MCOP;, где большая часть реализаций <acronym>CORBA</acronym> явно проигрывает. </para>
<para>При получении массива строк нужно отслеживать длину каждой строки, чтобы узнать, когда закончится массив. Хотя если вы используете строки для чего-то важного, это нужно делать в любом случае. </para>
<entry><para>см. <type>long</type>; отличия: содержит длину строки и последовательность символов, которая обязательно оканчивается нулевым байтом (он включён в длину)</para>
<entry><para>см. байт; содержит 0, если <returnvalue>false</returnvalue>, и 1 если <returnvalue>true</returnvalue>; значение <returnvalue>true</returnvalue> выглядит так:</para></entry>
<entry><para>упаковывается в соответствии с четырёхбайтовым представлением IEEE754 -подробнее об этом можно узнать здесь: <ulink url="http://twister.ou.edu/workshop.docs/common-tools/ numerical_comp_guide/ncg_math.doc.html"> http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html</ulink> и здесь: <ulink url="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html">http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html</ulink>; например, значение 2.15 будет выглядеть так:</para></entry>
<para>При обращении к простому типу используется его имя. У структур и перечисляемых типов есть собственные имена. Последовательности являются указателями на *<replaceable>обычные типы</replaceable>, поэтому обращение к последовательности элементов типа long будет таким: <quote>*long</quote>, а к последовательности структур Header: <quote>*Header</quote>. </para>
<para>Однако это простой (и быстрый) способ обработки неблокового сообщения. Сего помощью сообщения могут быть получены в фоновом режиме. Если одновременно установлено несколько соединений, они будут параллельными. Вам не нужно будет проверять содержимое всего сообщения (чтобы узнать, когда оно закончится), нужен только заголовок. Это упрощает кодирование. </para>
<para>После получения сообщения оно может быть распаковано и обработано за один проход, без рассматривания случаев, когда получены не все данные (это гарантирует messageLength). </para>
<para>Если нужен метод однонаправленный - т.е. асинхронный без возвращения значения - это был он. Иначе вы получите сообщение с messageType = 2 (mcopReturn) </para>
<para>Чтобы вызвать объект, нужно знать, какие методы можно использовать во время работы с ним. Значения 0, 1, 2, и 3 methodID определены для конкретных задач: </para>
<para>Строго говоря, только методы <methodname>_lookupMethod()</methodname> и <methodname>_interfaceName()</methodname> разные для всех объектов, а <methodname>_queryInterface()</methodname> и <methodname>_queryType()</methodname> всегда одинаковы. </para>
<para>Что же такое methodID? Если вы вызываете метод, нужно передавать его номер, т.к. цифры в запросе &MCOP; обрабатываются гораздо быстрее строк. </para>
<para>Итак, как же получить номер метода? Зная его подпись - MethodDef (в которой содержится имя, тип и информация о параметрах) - вы можете передать её в _lookupMethod объекта, вызывающего метод. Так как _lookupMethod настроен на methodID 0, проблем с этим не будет. </para>
<para>В связи с тем, что в &kde; отказались от <acronym>CORBA</acronym> полностью и используют вместо него &DCOP;, обычно возникает вопрос, почему это не делается в &arts;. Тем не менее в <classname>TDEApplication</classname> есть хорошая поддержка &DCOP; для интеграции с libICE. </para>
<para>Возможно, многие захотят спросить, зачем нужен &MCOP;, если есть &DCOP;, поэтому скажу сразу. Поймите меня правильно, я не хочу сказать, что <quote>&DCOP; - это плохо</quote>. Я просто хочу сказать, что <quote>&DCOP; не подходит &arts;</quote> (хотя это хорошее решение для других задач). </para>
<para>Во-первых, нужно понять, для чего был написан &DCOP;. Созданный за два дня на встрече &kde;-2, он должен был быть как можно более простым, <quote>легковесным</quote> протоколом связи. При разработке были упущены все сколько-нибудь сложные вопросы, например, подробное описание, как упаковывать типы данных. </para>
<para>Хотя в &DCOP; не важны некоторые вещи (например, как нужно посылать строку, чтобы обеспечить прозрачность сети?) - они необходимы. Поэтому всё, чего не может делать &DCOP;, добавлено в &Qt;. В основном, это управление типами (с помощью оператора сериализации &Qt;). </para>
<para>&DCOP; замечательно работает, позволяя приложениям &kde; отправлять простые сообщения вроде <quote>открыть в окне http://www.kde.org</quote> или <quote>данные о конфигурации изменились</quote>. Однако в &arts; важно другое. </para>
<para>Идея заключается в том, что небольшие модули &arts; должны общаться с помощью таких структур данных, как <quote>события midi</quote> и<quote>указатели на позицию в песне</quote>. </para>
<para>Это сложные типы данных, которые должны пересылаться различными объектами как потоки или параметры. В &MCOP; есть возможность определить сложные типы через простые (похожие на структуры или массивы в C++). В &DCOP; программист должен сам писать, например, классы и проверять, что они правильно сериализуются (к примеру, поддержка потокового оператора в &Qt;). </para>
<para>Но в этом случае они будут доступны только для C++, так как нельзя разработать язык, который будет распознавать все типы модулей (которые не будут самоописывающимися). </para>
<para>Почти та же проблема с интерфейсами. В объектах &DCOP; информация о связях, иерархии наследования и т. д. закрыта. И если вам нужно написать приложение, которое должно показывать, <quote>какие атрибуты есть у этого объекта</quote>, у вас ничего не получится. </para>
<para>Матиас (Matthias) рассказал, что есть специальная функция <quote>functions</quote> для каждого объекта, которая определяет, какие методы поддерживает объект. Она пропускает информацию об атрибутах (параметрах), потоках и наследовании. </para>
<para>Это серьёзно нарушает целостность таких приложений, как &arts-builder;. Но не следует забывать, что &DCOP; разрабатывался не как объектная модель (как &Qt; с <application>moc</application> и подобными), не как что-то вроде <acronym>CORBA</acronym>, а только для обеспечения связи между приложениями. </para>
<para>Отличие &MCOP; состоит в том, что он должен работать с потоками, которые являются основным способом сообщения между объектами. В <acronym>CORBA</acronym>-версии &arts; приходилось разделять <quote>объекты SynthModule</quote>, которые создавали потоки, и <quote>интерфейс <acronym>CORBA</acronym></quote>. </para>
<para>Основную часть кода занимала реализация взаимодействия <quote>объектов SynthModule</quote> и <quote>интерфейсов <acronym>CORBA</acronym> </quote>, она должна быть органичной, но не была, т.к. в <acronym>CORBA</acronym> не было даже понятия "поток". Взгляните на этот код (что-то вроде <filename>simplesoundserver_impl.cc </filename>). Он выглядит намного лучше! Потоки можно объявлять в интерфейсах модулей, а их использование выглядит естественно. </para>
<para>Этого нельзя отрицать. Одной из причин написания &MCOP;, была скорость. Вот несколько объяснений, почему &MCOP; будет работать быстрее &DCOP;. </para>
<para>Вызов в &MCOP; содержит заголовок из 6 чисел типа long: </para>
<para>После этого последуют параметры. Заметьте, что распаковка при этом очень быстра. Вы можете использовать стандартные функции для распаковки объекта или метода, что сводит сложность кодирования к минимуму. </para>
<para><application>DCOPserver</application> (посредник) получает его, решает, куда нужно отправить запрос, и отправляет его <quote>настоящему</quote> серверу. </para>
<para>Если и то, и другое было выполнено правильно, всё равно передача запроса через &MCOP; в два раза быстрее. И всё же есть причины выбрать&DCOP;: если запущено 20 приложений, все они связаны друг с другом, в &DCOP; нужно 20 соединения, а в &MCOP; 200. Однако в работе с мультимедиа это не распространено. </para>
<para>Я пробовал сравнивать &MCOP; и &DCOP;, делая вызов как сложение двух чисел, подправив testdcop. Но не смог получить точные результаты для &DCOP;. Метод вызывался в том же процессе, где был вызов &DCOP;, и я не знал, как избавиться от одного сообщения об отладке, пришлось перенаправить выход. </para>
<para>В тесте использовлись один объект и одна функция. С увеличением количества объектов и функций результаты &DCOP; ухудшаются, ау &MCOP; остаются прежними. Кроме того, задача <application>dcopserver</application> не была подключена к другим приложениям. Возможно, в этом случае, работа маршрутизатора была бы медленнее. </para>
<para>Наконец, полученный результат: чуть больше 2000 вызовов в секунду у &DCOP; и чуть больше 8000 вызовов в секунду у &MCOP;. В четыре раза. И я знаю, что это не предел &MCOP; (для сравнения: mico в <acronym>CORBA</acronym> совершает 1000-1500 вызовов в секунду). </para>
<para>Если вы хотите более точных данных, напишите небольшие приложения для сравнения с &DCOP; и пришлите их мне. </para>
<para>В <acronym>CORBA</acronym> была возможность использовать однажды вызванный объект как <quote>отдельный серверный процесс</quote> или как <quote>библиотеку</quote>. Можно было использовать один и тот же код, а <acronym>CORBA</acronym> уже сам решала, что делать. Насколько я знаю, в &DCOP; такое невозможно. </para>
<para>С другой стороны, в &MCOP; это обязательно должно быть. Поэтому вы можете прослушивать какой-то эффект в &artsd;, а при этом редактор звуковых файлов использует его в своем пространстве задачи. </para>
<para>Если &DCOP; - это способ передачи данных между приложениями, то &MCOP; - связь внутри приложений. Это особенно важно для потоков мультимедиа, т.к. можно запускать несколько объектов параллельно. </para>
<para>Хотя &MCOP; ещё этого не поддерживает, возможность помечать приоритет остаётся. Например, так: <quote>это событие &MIDI; намного важнее этого вызова</quote>. Или так: <quote>должно быть получено вовремя</quote>. </para>
<para>С другой стороны, в &MCOP; может быть интергрирована передача потоков, объединённая с <acronym>QoS</acronym>. Если это будет сделано, &MCOP; не будет работать медленнее, чем <acronym>TCP</acronym>, но будет проще в использовании. </para>
<para>Нет необходимости писать связующее ПО для мультимедиа в &Qt;, иначе оно станет &Qt;-зависимым. </para>
<para>Насколько я знаю, тип пересылаемых по &DCOP; данных не важен, поэтому &DCOP; может использоваться отдельно от &Qt;. Вот пример повседневного использования в &kde;: пользователи посылают типы <classname>TQString</classname>, <classname>QRect</classname>, <classname>QPixmap</classname>, <classname>QCString</classname>, ... Они используют сериализацию &Qt;. Поэтому если кто-то решит включить поддержку &DCOP;, например, в GNOME, он не сможет использовать типы <classname>TQString</classname> и др. и ему придётся эмулировать работу &Qt; с потоками или посылать строку, пиксельные изображения и типы rect, что, конечно, никуда не годится. </para>
<para>&arts; не привязан к &kde;, он может работать как с &Qt; и X11, так и без них, и даже без &Linux; (я знаю людей, у которых он нормально работает в распространённых коммерческих ОС). </para>
<para>Я считаю, что компоненты, написанные не для &GUI;, не должны от него зависеть, чтобы была возможность более широкого их распространения среди разработчиков. </para>
<para>Я понимаю, что использование двух протоколов <acronym>IPC</acronym> неудобно, однако переход на &DCOP; я не считаю выходом. При желании можно попытаться объединить два протокола. Можно даже научить &MCOP; говорить на <acronym>IIOP</acronym>, получится <acronym>CORBA</acronym> <acronym>ORB</acronym> ;). </para>
<para>Мы разговаривали с Матиасом Этрихом (Matthias Ettrich) о будущем двух протоколов и нашли множество путей их развития. Например, &MCOP; мог бы осуществлять передачу сообщений в &DCOP;, это бы сблизило протоколы. </para>
<para>Поэтому возможными решениями могли бы быть: </para>
<para>Создание шлюза &MCOP; - &DCOP;, который осуществлял бы взаимодействие этих протоколов. Если вы заинтересовались, спешу сообщить, что рабочий прототип уже существует. </para>
<para>Интеграция в &MCOP; всего, чего пользователи ожидают от &DCOP;. Попытаться работать только с ним. Кто-нибудь может добавить в &MCOP;<quote>сервер-посредник</quote> :) </para>