Tuesday, December 9th, 2008
Сегодня в сети появилась статья “Еще одно сравнение Adobe Flash и Silverlight 2” , прочитав ее я понял главную ошибку авторов этих статей — каждый автор является специалистом только в одной области, или Flash|Flex или Silverlight. Поэтому страдают “конкурирующие платформы”. Как выход я вижу написание совместной статьи (но это дело долгих споров). Автор данной статья не избежал ошибок и показал всое поверхностное знание Flex/Flash технологии.
Я попытаюсь исправить его недочеты, для полноты картины )
В начале оговоримся что я не буду в ходе разговора использовать софт который находится в стадии альфа, бетта и пререлиз ).
Среда разработки и прочий инструментарий.
Для начала разберемся с инструментраем и возможностями:
FlashPlayer — это плагин который позволяет проигрывать swf файлы (байт код, который можно создавать где и как угодно, например умельцы рантайм генерят его и сразу же запускают в флешплеере).
Flash IDE/Flex Builder — это среда позволяющая создавать swf файлы.
Flex framework — это фреймворк позволяющий быстро и эффективно создавать RIA приложения. Flex Builder “заточен” для работы с Flex framework.
Использование Flash IDE как средство разработки крупных приложений, довольно опрометчивый шаг. Ее, в контекте разработы RIA лучше использовать как дополнительное средство.
Вообще не стоит говорить что вся разработка сводится к связку Flash IDE(графика)-Flex(код) — это просто частный случай варианта разработки.
а использовать только Flex сложно, поскольку ничего похожего на дизайн-вью в нем просто нет.
Ляп! пожалуйста, жмем на кнопку Design в MXML редакторе и видим дизайн вью. (единственно что он не работает в билдере под линукс). Может канечно этот дизайн вью и не такой навороченый как бленд, но он есть )
Язык программирования
ActionScript 3 являеться вариантом реализации ECMAScript-262, 4 версии http://en.wikipedia.org/wiki/ECMAScript , Я не буду искать подробности отличая от этого стандарта, они есть и это можно найти воспользовавшись гуглом ).
Язык не имеет …
Да язык часто ругают за его непродвинутость.
Язык не имеет встроенной событийной модели
но это вот ляп, событийная модель является главной фичей флешплеера 9 и выше.
— кстате автор нигде не учитывал возможности флешплеера 10 ) который уже вышел в релиз.
Отдельной строкой хочется сказать об отладчике.
Если во Flex Builder он еще куда ни шло, то во Flash им просто невозможно пользоваться – основным методом отладки до сих пор является trace.
При разработке крупных проектов боже вас упаси использовать и дебажить во Flash IDE! вы же не будете дебажить в Blend’e 😉
Поддержка ОС и браузеров:
А что есть нормальная(официальная) поддержка Linux? Как мне поница Moonlight дорос пока только до версии 1. вобщем то до релиза далеко.
К том же плеер более стабилен в различных системах. (мне порой приходится перегружать барузер или запускать ИЕ чтобы посмотреть приложение на Silverlight, Маководы жалуются что не всегда получается поставить плагин)
Возможность упаковки в исполняемый файл:
Стоит учитывать что есть продукты сторонних производителей которые позволяют делать испольняемые файлвы из флеш/флекс приложений, причем под разные платформы (например Zinс)
Изображения:
JPEG, GIF, PNG — флеш с этим работает на лету. Вектор, у флеша это в крови. Кроме того, что можно импортировать ai,пдф файлы автор забыли о поддержке SVG графики. Причем уже есть библиотреки позволяющие использовать ее рантайм. (Например degrafa http://www.degrafa.com/2007/07/27/how-complex-can-you-get-with-degrafa-very/).
Также можно реализовать поддержку практичеки любого формата графики (ByteArray+Bitmap+Drawing API).
Про скорость отрисовки я бы вообще ничего не говорил, как не крути у флешплеера она больше.
А проблемы подготовки графики это уже проблемы кривых рук.
Видео:
flv это хорошее сжатие, но и возможность лайфстриминга, перемотки и других фич
из коментариев:
+ есть поддержка HD video
Флешплеер это тоже поддерживает.
+ теоретически, поддержку flv можно реализовать самому, используя MediaStreamSource (тут есть примеры http://code.msdn.microsoft.com/ManagedMediaHelpers)
нужна практика а не теория, хотя такой возможностью флеш не может покак порадовать.
Как не крути пока приоритет на стороне флеша
Шрифты:
Имеет три встроенных шрифта, поддерживается импорт символов из шрифтов ТТF, ограниченно поддерживаются шрифты, установленные в системе.
просто глупость.
Мы можем влючить любой шрифт в наше приложение, и он будет работать везде.
3 шрифта, тоже глупость, Просто по умолчанию флекс компоненты используют заданые шрифты, и нечего более.
Формально, не импортированные шрифты поддерживаются. Однако, с текстом, напечатанным таким шрифтом, почти ничего нельзя делать: ни поворачивать, ни масштабировать, ни использовать в качестве маски.
Раньше (9 и ниже версии плеера) и вправду не позволяли таких операций как вращение, масштабирование (вытягивание по какой-то оси), в 10 плеере вы можете делать с любым шрифтом, что угодно и как угодно.
Сокеты:
незнаю что твориться в Silverlight, но в FlashPlayer к сожелению имеет некоторые ограничения 🙁
Работа с файлами:
Принципиальное преисущество было у Silverlight до выхода 10 версии флешплеера, теперь его нет ).
Хранение данных на клиенте:
хе хе пункту просто не зачет. никак не может влиять на оценку платформы.
Разметка:
Спорный вопрос. Я бы не ставил плюса ни одной из технологий.
Если говорить о скором будующем то будет революция 😉 Ключевое слово Flash Catalyst
«Программное» рисование:
Незнаю как обстоят дела в Silverlight, но во флеш им можно творить чудеса.
«Программная» анимация:
Flash/Flex: Основана на фрэймах.
Никто не мешает использовать верменные интервалы. т.е. больше возможностей ).
Я не спец в этой области и пусть те кто работают с FlashCS3|CS4 добавят свои коменты. ).
Собственные контролы:
Автор описал только один, довольно причудливый способ :).
Да. Визуально не всегда сразу можно посмотреть на внешний вид компонента.
Опять же для спора и нахождения истены в данном вопросе нужно сначало определиться с понятием “Собственный контрол”.
Кастомизация контролов
Я незнаю как работают стили в WPF, но
ни все равно почти начисто обходит css-образные стили Flex, которые по сути не многим более чем обычные словари, которые можно хранить в отдельных файлах. Стили во Flex не поддерживают байндинга, не позволяют задавать темплейты, не имеют строгой типизации, и уж тем более не позволяют хранить внутри себя анимацию, не умеют изменятся в зависимости от каких-либо условий.
Полный бред. Для начала ознакомтесь с возможностями стилировния, затем полистайте примеры на той же Деграфе. Стили во флексе ограничиваются только фантазией, как только она закончилась, так и закончились стили )
Связывание данных
Да, во Flex не создается как таковой объект биндинга
Он то создаеться, но вот доступа мы к нему не имеем. Также есть возможность создать биндинг в коде BindingUtils
А двусторонний биндинг, единственный пока что козырь Silverlight, во Flex добавят в Gumbo.
В Flex 2|3 это также легко реализуется, как в коде так и с использованием MXML 🙂
Реализация MVC
Flex Framework и есть реалиация MVC просто она скрыта от глаз программистов. Поэтому они не разобравшись пугаються и пытаюстся насочинять своих фреймворков ).
А насочиняли их уже много Cairngorm/PureMVC/Mate/Guasax/Model-Glue… и так далее.
Вроде пока все, что пришло на ум.
Поэтому я бы не спешил делать такие опрометчивые выводы, незная не платформы, и незная текущего состояния вещей.
В скором вермени (2009 год) Adobe ух как пошатнет преимущества разработки под сильверлайт, И я бы не стал говорить, что “с точки зрения удобства для разработчика “серебренный свет” уже вне досегаемости”.
Единственными весомым преимуществами Silverlight является:
– большее количество “тяжолых” разработчиков, которые прошли огонь и воду в програмирование под C# и т.д. В отличаии от разработчиков Flex которые в большей части работали во Флеш
– политика отношения Microsoft к разработчикам, ее тактика “Мы везде и никто кроме нас)”. Обучение, бонусы и т.д.
ЗЫ
Неосвещенным остался вопрос производительности, но это тема для отдельного большого исследования.
Как показывает практика FlashPlayer быстрее в графике, как не крути, нельзя сказать что намного, но все же приятно 🙂
Posted in ActionScript 3.0, Flash, Flash Player, Flex, Flex Builder 2, Flex Builder 3, flex framework, mxml, RIA, Silverlight, Skinning | 16 Comments »
Wednesday, October 10th, 2007
Почему же не получилось шоколада?
Причин в этом несколько.
1. Стабильность
Когда я был маленький, у нас вел программирование “злой дядя” Овсянник В.Н. , “злым” его считали за то, что он валил практически любую программу принесеную на ему на здачу (дз или курсач). Делал он это довольно просто – брал и вводил неадекватные данные (если нужно было ввести строку то пихал в нее этак символов 500, или нажимал клавиши кнопки не в той последовательности), и ПО юного программиста падало. Это было его первым действием и оно было на эффективно почти на все 100%. Естественно юные таланты отправлялись дорабатывать свою программу.
Таким способом я поступил со своим прототипом плеера. Получилось полная лажа.
Если у нас кроме плей и стоп, есть премотка, а еще не дай бог мы решили менять source у
VideoDisplay, то плеер наш “держится” аж 10-15 секунд усиленого клика ). Потом он уходит в ступор и уже не реагирует на кнопки и обратно уже не возвращается, о своем плохом состоянии он ничего никому не говорит. UPD: говорит, и возвращаеться! только ждать нужно ооооочень долго, в зависимости от наклацаного и коннекта у меня оказываеться просто не хвалило терпения дождаться, дождется ли пользователь? Помогает только F5.
2. Удобство для пользователя
Пользователь, сука, нервный.
Моделируем ситуацию 1:
Я пользователь зашел посмотреть видео. Есть небольшой плейлистик и не очень быстное соединение (или у пользователя или напрягли сервер). Я выбираю видео, жду, но тут я понимаю что рядов в списке именно то видео которое меня интересует больше, поэтому жму на нем. И мне хочется чтобы оно заиграло быстренько заиграло ну я начинаю пыцкать плей, потом думаю что нужно чтобы забуфирилось жму паузу, затем еще раз плей. тут на помощь приходит наш пункт 1 Стабильность и плеер падает) на очень долго задумывается, настолько что можно подумать что висит(.
Ситуация 2:
Я пользователь смотрю видео, но некоторые места мне не интересны я начинаю кликать по перемотке и если не дай бог какие-то тормоза (коннект, или машина слабая) и плеер не успевает мгновенно отреагировать то я кликаю еще раз что только усилывает тормоза, затем еще раз… а потом я решаю вернутся назад… вобщем кликаю много.
В при использовании VideoDislpay это вообще фатально ибо, у него не точный seek, что особенно заметно на очень маленьких роликах, он хранит всю(!) истории этих кликов (вернее команд перемодки). т.е. при перемотки он перематывает сначало на первый клик, раздупляется, мотает на второй, и т.д. А пользователь за время раздупления может сделать 5 кликов. И они все отобразятся. Выглядит просто это супер особенно если мотать на разные места, такая машина времени ), пользователь начинает нерничать и кликает еще и еще и плееру становится все хуже и хуже… Я пробовал – можно наклацать так что этот дергаться будет еще секунд 30 :D, а иногда оно просто уходит в ступор.
Вобще если учесть, что “пользователь, сука, нервный” то есть вероятность того, пользователь натрахавшись с удобствами (пусть даже если он сам дурак) просто закроет страницу и больше никода не придет посмотреть ваше видео. В принципе можно запретить все эти возможности если это всего несколько роликов и сайт специализируется на чем-то другом, а если это сайт специализирующийся на видео?
3. Удобство для разработчика
После того как я обернул VideoDisplay захотев шоколада, я захотел исправить ситуацию с неточностью у seek’a. Seek живет все в том же VideoPlayer, уже стало немного страшно. Но не теряя оптимизма я ринулся в бой. В VideoDisplay, плеер (VideoPlayer) объявлен как
[code lang=”actionscript”]
mx_internal var videoPlayer:VideoPlayer = null;
[/code]
вроде ниче страшного, дальше у VideoPlayer есть public метод seek – вообще замечательно, т.е. если сделать класс наследник от VideoDisplay и ему всесто VideoPlayer подсунуть наследника от VideoPlayer с оверайднутым seek’oм ситуация будет спасена. Но не тут то было публичный seek у VideoPlayer’а это иллюзия, фактическая перемотка происходит в приватном методе _seek который использует приватные переменные VideoPlayer’а причем одна из перменных является экземпляром класса VideoPlayerNetStream (наследник от NetStream), который объявлен в самом VideoPlayer.as, т.е. видимость этого класса начинается и заканчивается VideoPlayer’ом. Ну и за ними также тянуться все классы из mx.controls.videoclasses.*. Вобщем-то приплыли.
В результате получили чтобы доработать напильничном пару методов нужно копипастить все классы из mx.controls.videoclasses.* в свой пакетик, делать децельный рефакторинг (небольшой минут 15), потом брать свое приложение и менять в нем mx.controls.VideoDisplay на moy.mega.noviy.VideoDisplay и после этого мы готовы переписать требуемые методы.
Скажите не правдали удобно? на онанизм не похоже? Помоемому похоже.
Вобщем так и было вначале сделано, потом полезли всякие неприятности по стабильности плеера, это “приятная” очередь из seek’ов, уходы плеера в астрал если слишком много клацали по клавишам и т.д.
Сначало была мысль вылечить сам VideoPlayer, но посмотрев еще раз код, всего 3к строк (правда включая коментарии) + то что еще он супер универсальный
VideoPlayer is an easy to use wrapper for Video, NetConnection,
NetStream, etc. that makes playing FLV easy. It supports streaming
from Flash Communication Server (FCS) and http download of FLVs.
примая во внимание всего десяток таймеров, чужой полет чужой мысли, и то что конечный VideoDisplay все равно придется дорабатывать кувалдой-молотком-напильником было принято решение положить орган на эту ветку эволюции и начать свою ветку эволюции (или деградации).
Выводы
- Не все то золото что блястит.
- VideoDisplay тупиковая ветка развития. UPD: все еще можно исправить? Лучшее решение это ждать что адоб сам исправит ситуацию
- Вывод VideoDisplay из тупика своими не поддается оценке времени в человекочасах и никому это особо не нужно при таких раскладах UPD: не все потеряно) Достаем бубен из кармана?
- Возвращаемся к истокам (Video) и пытаемся родить свой работоспособный, пользователеустойчивый(с) аналог VideoDisplay учитывая, что
- нам не нужно (пока) support streaming
from Flash Communication Server (FCS)
- Конструкция должна быть легкая и устойчивая в примении
- Постаратся использовать чуть меньше таймеров 🙂
- Нам не нужен хоровод из сиков
- его внедрение в готовый код должно занять минимум усилий
Текущий результат
Имеем пока кучу потраченого в никуда времени и плеер который работает, если ничего не трогать.
В следующих сериях вы услышите увлекательные рассказы о NetStream и Video.
UPD: Мотыль Нарожняк подсказал новую ветку развития событий и еще раз показал, что не нужно суетится, а нужно изучать доки как можно внимательнее, [тут еще пара отмазок почему это произошло]).
Но всеравно NetStream”y достанется 😉
Posted in ActionScript 3.0, Flex, Video | 5 Comments »
Wednesday, October 10th, 2007
Вообще-то вся правда о видео начала выеснятся именно из практического применения. Мне нужно было написать видео плеер, обычный без наворотов (плей/стоп/пауза/перемотка/че загрузили).
Добавил я VideoDisplay на сцену, кинул слайдер, кнопки, добавил обработчики. Ничего вроде сложного. Но не тут то было. Если с плей/стоп более мение понятно то с перемоткой сразу возникли проблемы. Сначало это туева хуча эксепшинов, если пользователь совершил шаг влево или вправо, причем по всем поводам заиграл null урл, перемотал куда-то вдаль или близь. Подумал, что я что-то не так делаю…
——-
Немного оффтопа:
Почему я ругаю адоб (вернее индусов которые там работают), я просто зол на них, а почему я зол на них? Я не считаю себя супер программистом, или гением и “по умолчанию” я считаю что в комманде разработчиков адоба работают не дураки и всем есть чему у них поучиться (не зря ж они работают там). Поэтому я изначально доверяю их коду, а если прибавить рекламу что “все стало удобнее и легко, и делается все с пол пинка” то и вроде доверия больше. Исходя из этих тезисов получается такая конструкция “Если у тебя что-то не работает, а адоб крут, то наверное это глюк в твоем коде, проверь все 3 раза”.. После чего ты проверяешь пару раз свой код, читаешь хелп, копипастишь из него примеры, а оно нихера не работает. И тут закрадывается сомнение, а может таки это косяк в коде от адоба? Начинается колупание в коде фреймворка. Вы скажете ну и что колупайся, ищи, изучай пиши свои решения, модифицируй существующий код. Я с этим почти согласен, но тут есть одно мрачное НО – это эстимейт. Когда делается проект у него есть сроки, чтобы выставить эти сроки, таратится время на изучение возможности реализации и сроков реализации той или иной функциональности. Естетсвенно почитав оптимистичные доки от адоба “а тут все в пол пинка делается”, прикинув вероятные трудности, ты устанавливаешь сроки реализации проекта, ушлый клиент тоже не дремлет, он тоже знает о фичах и если ты ему скажешь, что я заскиную тебе скрол за месяц, то он очень удивится, и скажет батенька да вы гоните тут работы на 2 часа. Потом придя к взаимовыгодному решению, заполнив бумажки вы стартуете проект, клиент ждет. После этого начинаеться самое интересное, делаешь это “пол пиночное” решение и видишь что ничего не работает, проверяешь себя пару раз(на проверку время-то тратится), вроде все правильно, лезешь в фрейворк начинаешь смотреть там (а миноточки и часы идут), фрейворк не маленьки, вы наверное это заметили ? )), зависимостей много, в результате найдя в чем проблема вы пытаетесь ее решить, сначало малой кровью (очень часто так не получается), затем уже глобальными способами, а время бежит, и способа сделать 36 часов в сутки никто еще не предложил. В итоге мы имеем просроченный дедлайн, если клиент адекватный и ему можно объяснить почему так, то все вроде хорошо, а если нет + мы имеем моральное неудовлетворени, нервотрепка, стрессы, вобщем нету кайфа от процесса. Поэтому я зол на адоб, ну на себя тоже (ибо я не идеален), но видоваты оба (хотя я люблю себя любимого, поэтому адоб больше %) ). Наверное эта ситуация знакома каждому?
——–
…Подумал, что я что-то не так делаю, или я “просто не умею его готовить”, перелопатив свой код я не нашел подвоха, полез во фреймворк и увидел в коде VideoPlayer следующее
[code lang=”actionscript”]
…..
public function play(url:String = null, isLive:Boolean = false, totalTime:Number = -1):void
{
…..
if (!isXnOK())
{
if (_state == CONNECTION_ERROR ||
_ncMgr == null ||
_ncMgr.netConnection == null)
throw new VideoError(VideoError.NO_CONNECTION);
else
{
….
[/code]
Бабах эксепшин, всего лишь 7 эксепшинов бабахается в VideoPlayer на неверный play, pause, seek и т.д. Так лезем в доку, в чем проблемы то, дока молчит, но посмотрев коментарий у VideoPlayer.play() вижу следующую инструкцию
[code lang=”actionscript”]
…
* Throws an exception if called with no args and no stream
* is connected. Use “stateChange” event and
* connected property to determine when it is
* safe to call this method.
…
[/code]
упс, думаю я, читатать нужно внимательнее хелп, но потом вспоминаю в хелпе нету этого класса, этот класс спрятан от чужих глаз!
Проверил VideoDisplay, там тоже никто ничего не проверяет.
Ну что же подумал я, не вопрос дабы сильно не напрягатся наследуюсь от VideoDisplay, оберну эти методы проверочками, не пущу эксепшины дальше и будет все в шоколаде. Обернул. Шоколада не получилось.
Posted in ActionScript 3.0, Flex, Video | 1 Comment »
Monday, October 8th, 2007
Теперь переходим к VideoDisplay – это просто ахтунг!
В видео дисплее живет класс который называется VideoPlayer (mx.controls.videoClasses.VideoPlayer). Это сущее порождение зла), что мы можем узнать о нем? В хелпе его нету, заглянем ка во внутрь ради спортивного интереса
[code lang=”actionscript”][ExcludeClass]
/**
* @private
* VideoPlayer is an easy to use wrapper for Video, NetConnection,
* NetStream, etc. that makes playing FLV easy. It supports streaming
* from Flash Communication Server (FCS) and http download of FLVs.
*
* <p>VideoPlayer extends Video.</p>
*
* @tiptext VideoPlayer: FLV player
* @helpid ???
*/
public class VideoPlayer extends Video
….
[/code]
Едить-колотить да это супер клад который легко позволит нам работать с видео! Но почему же мы его не видим нигде? да потому что он сырой, недоделанный, причем по коментам сразу видно, что его тупо не успели сделать и спрятали с глаз долой – “только фанаты заглянут внутрь”.
теперь листаем дальше. А там [цензура][цензура][цензура][цензура][цензура]!
[code lang=”actionscript”]
//———————————-
// default times for intervals
//———————————-
public static const DEFAULT_UPDATE_TIME_INTERVAL:Number = 250; // .25 seconds
public static const DEFAULT_UPDATE_PROGRESS_INTERVAL:Number = 250; // .25 seconds
public static const DEFAULT_IDLE_TIMEOUT_INTERVAL:Number = 300000; // five minutes
public static const AUTO_RESIZE_INTERVAL:Number = 100; // .1 seconds
public static const AUTO_RESIZE_PLAYHEAD_TIMEOUT:Number = .5; // .5 seconds
public static const AUTO_RESIZE_METADATA_DELAY_MAX:Number = 5; // .5 seconds
public static const FINISH_AUTO_RESIZE_INTERVAL:Number = 250; // .25 seconds
public static const RTMP_DO_STOP_AT_END_INTERVAL:Number = 500; // .5 seconds
public static const RTMP_DO_SEEK_INTERVAL:Number = 100; // .1 seconds
public static const HTTP_DO_SEEK_INTERVAL:Number = 250; // .25 seconds
public static const HTTP_DO_SEEK_MAX_COUNT:Number = 4; // 4 times * .25 seconds = 1 second
public static const CLOSE_NS_INTERVAL:Number = .25; // .25 secconds
public static const HTTP_DELAYED_BUFFERING_INTERVAL:Number = 100; // .1 seconds
[/code]
представляете какую жопу можно организовать с таким количество таймеров, но не переживайте все 13 интервалов (интересное количество, наверное им все и объясняется) мы использовать не будем, в конструкторе мы проинициализировали всего лишь 9(!) таймеров. Я лично поставлю ящик пива кто сможет не запутавшись, написать и гарантировать мне корректность работы с таким количеством таймеров. А если еще добавить сюда NetStream который подкидывает программеру еще разные приятности, то хочется сказать:
“Респект и Уважуха Адобу! С его лучшим видео!”
а еще спасибо за все заботы о бедных программистах.
В следующих выпусках мы поговорим о практическом применением VideoDisplay и чем это грозит, поговорим NetStream’e и может что-то достанется и Video. До встречи
Posted in ActionScript 3.0, Flex, Video | 8 Comments »
Monday, October 8th, 2007
Начнем с буфера у Video в 9 плеере/AS3.
Раньше было все хорошо, при проигрывании буфер равнялся порции видео которое было доступно для проигрывания/перемотки. Но индусы поразмыслив решили, что это лишняя информация о которой программеру вообще не нужно знать, и теперь мы имеем буфер в размере “децл” по умолчанию он скачет где-то 0.1 – 0.2 секунды, если мы задали буфер ручками то это наше число + этот децл. Спрашивается нахера нам это нужно знать? Мне эта инфа совсем не нужна, мне гораздо интереснее знать на сколько я могу позволить пользователю подвинуть бегунок перемотки, сколько у меня фактически загружено, а не этот “важный” децл. Теперь с подачи индусов у нас отняли все более менее нормальные способы довести до пользователя состояния видео (всего каких-то 3 показателя длинна, сколько уже загружено(в секундах) и где мы играем). Остались только мега извраты для определения состояния видео если нету у видео мета тегов, но мега извраты мы не используем.
*Немного о мега извратах:
самый извратистый изврат это сделать seek в бесконечность в какой-то момент времени и он вернет количество секунд которые на данный момент. Располагая этой инфой можно в приблизительно прикинуть длину видео без мета тегов, и воссоздать наши 3 заветные величины. Но опять же это ИЗВРАЩЕНИЕ.
Скажем дружно “Респект и Уважуха Адобу! С его лучшим видео!”
Posted in ActionScript 3.0, Flex, Video | 1 Comment »