Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > alexcon314

Оценить эту запись

Расширение проектора: Продолжение 4. Синхронные вызовы.

Запись от alexcon314 размещена 19.08.2009 в 12:41
Обновил(-а) alexcon314 19.08.2009 в 17:57

Мда.. перерывчик вышел долгонький. Но он того стоил.
В "Продолжении 2" я говорил о том, что реализация оболочки на основе только класса LocalConnection не позволяет осуществить синхронное выполнение АС-кода и кода оболочки.
Цитата:
Из сказанного видно, что наша оболочка обладает одной весьма важной и не очень приятной особенностью: команды, отсылаемые оболочке выполняются асинхронно с кодом, их пославшим, т.е. с АС-кодом.
.. и далее по тексту.
Но, кто ищет - тот найдет! И нашел, кажется.
Общение плеера в внешним миром во время выполнения кода ролика может быть построено разными способами. Для этого есть классы, позволяющие подгружать данные из-вне и отправлять данные наружу. Те же LC, XML, XMLSocket, MovieclipLoader... Но работа с этими классами не подразумевает синхронного выполнения кода изначально, что диктуется логикой клиент-серверного взаимодействия: отправили запрос - ждем ответа. А ответ придет не мгновенно..
Но есть класс, который общается с внешним миром синхронно, это SharedObject.
Этот класс работает с файловой сисемой непосредственно, скажем возврат метода SharedObject.getLocal() произойдет, когда нужный шаред-файл будет считан и его содержимое будет разложено по полям в соответствующем объекте. Сравним два примера работы с XML и SO:
Код AS1/AS2:
var xml:XML = new XML();
xml.load("myXMLsource.xml");
// здесь содержимое объекта xml еще недоступно
// т.е. бъект здесь пуст, мы просто отправили "запрос"
// на чтение файла myXMLsource.xml.
// ...
xml.onLoad=function(success:Boolean){
	// ну вот, файл myXMLsource.xml прочитан.
	// только здесь мы можем что-то делать с
	// загруженным xml.
	// причем неважно, из сети грузим или с жесткого диска
}
var so:SharedObject = SharedObject.getLocal('mySOsource');
// файл mySOsource.sol уже прочитан.
// содержимое объекта so доступно уже здесь, в следующей строчке кода.
Разбор ошибок при чтении/загрузке я опустил.
Разница в том, что при работе с SO плеер выполняет файловые операции и AS-код в одном потоке. А значит, можно перехватить обращение плеера к диску, выполнить "оболочечный" код, и вернуть управление обратно. Т.е. код оболочки будет выполнен синхронно с АС-кодом.
В обращение к шареду на этапе записи можно зашить команду:
Код AS1/AS2:
var so_query:SharedObject = SharedObject.getLocal('mySOquery');
so_query.data.command = "команда_такая-то";
so_query.data.args = "строка_с_аргументами";
so_query.flush();
А на этапе чтения шареда подставить результат ее выполнения:
Код AS1/AS2:
var so_answer:SharedObject = SharedObject.getLocal('mySOanswer');
// все, в so_answer.data сидит ответ.
Осталось организовать два предыдущих фрагмента в виде функции, принимающей параметрами команду и ее аргименты, и возвращающую то, что пришло в so_answer.data.
Код AS1/AS2:
function execCommand(command:String, param:String):Object {
	var so_query:SharedObject = SharedObject.getLocal('mySOquery');
	so_query.data.command = command;
	so_query.data.args = param;
	so_query.flush();
	// вот здесь мы и перехватим попытку записи на винт.
	// и за одно узнаем, что плеер вознамерился записать,
	// т.е. команду и ее аргументы
// тут, собственно, и выполняется оболочечный код, формируется результат работы команды
	var so_answer:SharedObject = SharedObject.getLocal('mySOanswer');
	// a вот здесь мы перехватим попытку чтения
	// и запишем в буфер, припасенный плеером для этой операции
	// наши данные
	return so_answer.data;
}
// где-то в коде вызов
var result:Object = execCommand('команда','аргументы');
// объект result содержит результат выполнения команды. ву-аля!
Вот так это выглядит в упрощенном изложении.
Технически реализовать на строне оболочки перехват не так уж и сложно. Труднее подстроиться под реализацию работы c SO в плеере. Дело в том, что операции чтения/записи сопровождаются некоторыми предварительными действиями, как-то проверка файла на существование, определение его размера, чтение и применеие настроек LocalStorage, да и сам порядок этих действий варьируется в зависимости от последовательности действий с SO в АС-коде. Более того, как оказалось, 8-ой и 9/10-ый плееры применяют разные АПИ вызовы при работе с шаредами. Есть разница и в протоколе, т.е. 9-ка поддерживает и AMF0 и AMF3, 8-ка только AMF0. Есть некоторые заморочки с именами файлов SO. Вобщем, есть чисто технические сложности, но принципиальных препятствий для осуществления синхронных вызовов по такой схеме нет.
В настоящий момент мне удалось заставить работать синхронно с оболочкой 8-ой и 9-ый плеер (10-ку не проверял, но бегло осмотрев, увидел, что там то же, что и в 9-ке).
Потому, следующее "Продолжение", видимо будет не скоро. В связи, так сказать, с вновь открывшимися...
Но, преимущества такого подхода на лицо: упрощение кода, возможно создавать что-то на-вроде геттеров/сеттеров для классов оболочки, неограниченный объем передаваемых данных в обе стороны. Плюс остается LC, через него можно засылать ивенты в плеер, и осуществлять асинхронные операции, скажем, "анимировать иконку в трее в течение 10 сек." и т.п.)).

Ну, и в заключение, небольшой оффтоп.
Когда-то давно, я писал в каком-то топике (если вспомню, покажу) про глюк в цинке (<= 2.5.0.34), точнее про mdm.FileSystem.saveFile(). Глюк заключался в том, что при попытке сохранить за раз больше 100кб данных вываливалось плеерное окошечко "Settings.." c предупреждением о превышении размера LocalStorage. Если учесть, что по дефолту этот размер как раз и есть 100кб, то все это наводит на мысли, что разработчики цинка в тех версиях тоже юзали перехват обращений к диску через SO. Ни фига себе! Никогда бы не подумал! Вот тебе и ... mdm. Им что, СОМ-интерфейсов мало было? Хотя, скорее, неспроста все это ...
Косвенно это подтверждается еще и глюком с невозможностью сохранять шареды из цинка, кроме как в папку "/". Возможно, чего-то там с перенаправлением путей накосячили.
Во всяком случае, у меня это окошечко не вываливается)).
Всего комментариев 14

Комментарии

Старый 24.08.2009 14:53 chingachgoog вне форума
chingachgoog
 
Аватар для chingachgoog
Это хорошо, если удастся перехватить SO даже в том случае, если пользователь установит НЕ СОХРАНЯТЬ ни байта в SO (а он может сделать это для совсем другой флешки). А если нет? LC существует всегда и вне зависимости от предустановок других флеш-плееров.
Старый 24.08.2009 17:23 alexcon314 вне форума
alexcon314
Цитата:
если пользователь установит НЕ СОХРАНЯТЬ ни байта в SO
Это предусмотрено. Нарочно при инициализации всего этого хозяйства принудительно пишем в шаред что-то, это заставляет плеер обратиться к файлу с настройками (такой же .sol файл в особой папочке в профиле пользователя). Перехватываем чтение и подставляем нужный параметр.
Запускаю просто проектор - ограничение 100кб, например, показывает.(правая кнопка->Settings...).
Параллельно запускаю проектор с длл - показывает то, что я ему подсунул. Анлимит, скажем.
Если файл настроек отсутствует, прежде чем дергаться распаковываю дефолтный файл из ресурсов, дальше все как описано выше. При выходе удаляю.Хотя можно и оставить, в принципе.
Конечно, если работать с шаредами обычным образом - то лучше после инициализации оболочки, но это не страшно)).
К сожалению, полностью исключить обращения к диску не удается(( - вот это не есть кулл. Приходится иметь все же темповские шареды на винте, хоть и пустые.
Для восьмого можно было бы и без них, проверял и получалось. Но вот 9/10 - не хотят без них. Как-то хитро там организована работа с этими файлами, во всяком случае функции kernel32 юзаются меньше, CreateFile() вообще не юзаетсоя, к примеру.
Сейчас пытаюсь реализовать все это под AS3/AMF3.
Из AMF3 планирую реализовать string и byte array. Из AMF0 string и large string.
Обновил(-а) alexcon314 24.08.2009 в 17:30
Старый 31.08.2009 08:01 Яски вне форума
Яски
Круто. А наработками воспользоваться можно будет?
А вы не задумывались сделать подстановку машинного кода вместо AS3 кода прямо в памяти плеера? Например, создать класс-заглушку, после запуска его плеером и JIT компиляции подменить содержимое методов на вызов своего кода. Или даже заменить содержимое какого-либо стандартного класса — мне кажется JIT компиляция подобного кода должна происходить один раз. Зато получаем выполнение произвольного машинного кода из AS3 кода без издержек.
Старый 03.09.2009 15:49 alexcon314 вне форума
alexcon314
Наработки изначально планировал и планирую выложить как есть для пользования всеми желающими, ну, разве что, где-нибудь в уголке повешу кнопку "Donate")).
Не из великодушия и не из чванства, это просто мое увлечение-хобби.
Вашу идею обязательно обдумаю. Насколько я понял, описанное мной действие с шаредами - это что-то навроде, но, если так можно выразиться, влегкую. Вы предлагаете нечто более глобальное, несомненно.
Старый 04.09.2009 16:25 Котяра вне форума
Котяра
 
Аватар для Котяра
Очень полезно.
Вопрос оффтоп:
Есть необходимость запускать swf в directX приложениях (менюшки для игр).
в гугловских закромах обнаружил scale Form. Проблема в том, что он использует только as2. Не подскажешь похожих продуктов для as3?
Старый 06.09.2009 07:58 Яски вне форума
Яски
Я вот не пойму, зачем замарачиваться с 7/8/9 версией плеера? Библиотека же будет работать с проектором, а проектор можно создать в любой версии плеера — проще тестировать сразу для последней 10 версии плеера.
Старый 07.09.2009 15:08 alexcon314 вне форума
alexcon314
Яски, резонно, но, скажем так, не все разработчики осознают, как сделать 10-ый проектор, не имея под руками CS4. Была мысль сделать программку, которая генерит ехе под конкретную версию плеера с свф-ом, изготовленным все равно где, но изготовить такую программку невозможно, не нарушая лизензии. Ибо программка по-сути дописывает код свф в код автономного плеера, а это какая-никакая, а модификация. В настоящее время я "веду" 8/9/10 версии плеера и АС версий 2/3.

Котяра, я не знаю, что такое scale Form, ссылку дали бы что ли.. f-in-box не подходит для этих целей?
Думаю, что заэмбеддить ActiveX-плеер какой угодно версии отдельным или дочерним окном можно всегда. Если вы сами пишете код приложения и это си++, рекомендовал бы использовать ATL. Один раз разобраться - удовольствия на всю оставшуюся жизнь )).
Старый 07.09.2009 19:27 Котяра вне форума
Котяра
 
Аватар для Котяра
Цитата:
что такое scale Form, ссылку дали бы что ли..
http://www.scaleform.com/
http://en.wikipedia.org/wiki/Scaleform
Старый 07.09.2009 19:29 Яски вне форума
Яски
Создать проектор можно при помощи stand-alone плеера. Скачать его можно в любое время с сайта адоба.
Старый 17.09.2009 16:14 alexcon314 вне форума
alexcon314
Мм-да.. восьмой плеер глючит при таком использовании. Не дает четко выполнить запись-чтение шареда. Почему-то отрабатывает запись, чтение в пролете при последовательном вызове нескольких методов оболочки. Раньше за ним тоже наблюдались непонятные глюки при работе с шаредами, словно срабатывает какое-то непонятное кэширование однажды прочтенного шареда, одно время я даже пытался от этого избавиться путем присвоения случайного имени читаемому шареду, но отказался от этой идеи, ибо как-то неоправдано сложно все выходит.... Причем, АС2-ролик в 9-ом проекторе отрабатывает корректно, в 8-ом проекторе глючит. Видимо, придется установить "планку" не ниже 9-ой версии.
Все больше убеждаюсь в резонности замечания Яски о версиях проектора.
Котяра, увы, аналогов scaleForm не встречал.
Старый 09.10.2009 19:17 Skyggedans вне форума
Skyggedans
 
Аватар для Skyggedans
Уже неделю бьюсь с вызовом коллбэков (которые через ExternalInterface.addCallback() регистрируются) из флэшки, загруженной посредством NPSWF32. Вызываю метод Invoke() у скриптового объекта - тупо возвращает FALSE. Причем в оригинальном ScreenWeaver-е все отлично работает.
Перекопал уже весь код, инициализация проходит правильно, все структуры заполняются, метод вызываю из главного трэда, как положено. И хоть ты тресни...
Старый 05.02.2010 08:53 alexcon314 вне форума
alexcon314
Добил вчера класс для наложения ПНГ-маски на окно проектора. Маску можно брать из файла, из ресурсов длл/ехе или генерить налету в плеере. Можно так же цеплять анимированные гифы.
Обновил(-а) alexcon314 05.02.2010 в 08:56
Старый 05.02.2010 15:21 chingachgoog вне форума
chingachgoog
 
Аватар для chingachgoog
alexcon314, а каков механизм получения маски "генерить налету в плеере"?
Неужто удалось добраться до битмапы в AVM1?
Старый 05.02.2010 17:56 alexcon314 вне форума
alexcon314
не.. чисто перегон через BitmapData + getPixel32() из плеера в оболочку. К несчастью, в ас2 байт-массив еще и в строку сериализовать приходится. В ас3, конечно, все быстрее и проще через ByteArray.
Искать пока недосуг. Но, возможно, сделаю некий инструмент для исследований динамической памяти непосредственно из АС. Пока реализовал на уровне дампа заданного региона адресного пространства. Хочу попробовать ловить и анализировать маллоки и последующие операции над выделенной памятью.
Просто, все как всегда, идей много, авремени мало. До графического буфера пока только добраться получилось. Но что с ним делать, я не придумал.
 

 


Часовой пояс GMT +4, время: 21:52.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.