Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Высокоточный таймер

354
19 февраля 2006 года
ШпиЁн
468 / / 19.02.2006
Написал прогу для захвата всего происходящего на десктопе и записью в avi-файл со сжатием... Тормозит немного, но это еще цветочки... В общем, делаю так: ставлю таймер на 40 ms, использую SetTimer. Получается 25 fps при вызове таймера (в обработчике таймера просто доьавляются данные в видеопоток функцией AVIStreamWrite). Проблема - длина фрагмента оказывается меньше, чем реальное записываемое время... Значит, прога не успевает! виноват скорее всего, таймер, а не сжатие... без сжатия - все также... Где-то я встречал статейку о том, что обычный виндовский таймер очень нестабильный и работает с погрешностью около 4 ms при хорошей загрузке процессора... Так вот. Кто-нибудь знает, как сделать ТОЧНЫЙ таймер (QueryPerformanceCounter), НО чтобы вся эта конструкция не просто отсчитывала время, а являлась аналогом Sleep() ? :)))
398
19 февраля 2006 года
Alexandoros
630 / / 21.10.2005
Multimedia Timers в msdn посмотри. Он точнее будет и стабильнее.
354
19 февраля 2006 года
ШпиЁн
468 / / 19.02.2006
Цитата:
Originally posted by Alexandoros
Multimedia Timers в msdn посмотри. Он точнее будет и стабильнее.



эх.... да пробовал, работает так же, как и обычный SetTimer. Вообще-то мне надо аналог Sleep, но только более точный... Вроде можно как-то не загружать проц на 100 % ,если в цикле с QueryPerfomanceCounter использовать EnterCriticalSection(), но я об этом не наслышан... где-то ухватил, а вот из головы вылетело где :(

398
20 февраля 2006 года
Alexandoros
630 / / 21.10.2005
Попробовал я поигратся с критическими секциями, чето нифига не вышло. Говорят что виндовс не ось реального времени, и чтоб получить такой таймер нужно писать драйвер. Поэтому либо загрузка 100% либо дрова.
324
20 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by Alexandoros
Попробовал я поигратся с критическими секциями, чето нифига не вышло. Говорят что виндовс не ось реального времени, и чтоб получить такой таймер нужно писать драйвер. Поэтому либо загрузка 100% либо дрова.



У мьютекса есть такая фишка WaitForSingleObject. Она ждет освобождение критической секции в течение указанного времени. Что если одним потоком занимать критическую секцию на определенное время и не давать выполняться в это время основному потоку.
А таймер это такая штука, что для точных измерений его лучше не использовать. Т.к. его вызовы ставятся в очередь сообщений, и если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.

2.4K
20 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
...если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.


Это не так. Запросы не теряются(сами).

324
20 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Это не так. Запросы не теряются(сами).



В ходе проведенных лично мною "опытов" было установленно, что:
1. нельзя установить таймер менее чем на 15 мс (применительно к моей машине, причем независимо загружен ЦП или свободен);
2. запросы не теряются, а пропускаются

2.4K
20 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
В ходе проведенных лично мною "опытов" было установленно, что:
1. нельзя установить таймер менее чем на 15 мс (применительно к моей машине, причем независимо загружен ЦП или свободен);
2. запросы не теряются, а пропускаются



1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.

2. Приведи пример кода, где у тебя пропускаются запросы

534
20 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by dinasok51
1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.

2. Приведи пример кода, где у тебя пропускаются запросы

534
20 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by ШпиЁн
Написал прогу для захвата всего происходящего на десктопе и записью в avi-файл со сжатием... Тормозит немного, но это еще цветочки... В общем, делаю так: ставлю таймер на 40 ms, использую SetTimer. Получается 25 fps при вызове таймера (в обработчике таймера просто доьавляются данные в видеопоток функцией AVIStreamWrite). Проблема - длина фрагмента оказывается меньше, чем реальное записываемое время... Значит, прога не успевает! виноват скорее всего, таймер, а не сжатие... без сжатия - все также... Где-то я встречал статейку о том, что обычный виндовский таймер очень нестабильный и работает с погрешностью около 4 ms при хорошей загрузке процессора... Так вот. Кто-нибудь знает, как сделать ТОЧНЫЙ таймер (QueryPerformanceCounter), НО чтобы вся эта конструкция не просто отсчитывала время, а являлась аналогом Sleep() ? :)))


Если работаешь с Video Capture, не замудряйся с таймером. Сделай так: Переопредели обработчик CApp::OnIdle() или без MFC вместо GetMessage() используй if(!PeekMessage()){}. А уже там проверяй с помошью GetTickCount(): если с прошлого вызова данного обработчика прошёл необходимый интервал времени, ко капчи фрейм и жми. Если нет - return или Sleep(), таймер тебе здесь не нужен (да и вообще при работе с видео они не используются)

324
20 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.

2. Приведи пример кода, где у тебя пропускаются запросы



Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.

2.4K
20 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.


Кем вызывается? И как ты это видишь?

А про пример пропуска запросов не забудь пожалуйста

354
21 февраля 2006 года
ШпиЁн
468 / / 19.02.2006
Цитата:
Originally posted by HarryAxe
А уже там проверяй с помошью GetTickCount(): если с прошлого вызова данного обработчика прошёл необходимый интервал времени, ко капчи фрейм и жми. Если нет - return или Sleep(), таймер тебе здесь не нужен (да и вообще при работе с видео они не используются)



Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?

2.4K
21 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by ШпиЁн
Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?



Multimedia timer работает достаточно стабильно
Читал, что ты уже пробовал

Я получал 500 гц без загрузки процессора. Можно и 1кгц. но не выше.

Если интересно могу поделиться

324
21 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Multimedia timer работает достаточно стабильно
Читал, что ты уже пробовал

Я получал 500 гц без загрузки процессора. Можно и 1кгц. но не выше.

Если интересно могу поделиться



Как уже было сказано Windows не является ОС реального времени, поэтому для точных интервалов времени следует использовать специализированные библиотеки, например DirectX

534
21 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by ШпиЁн
Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?


НО, НАПОМИНАЮ, таймеры при работе с видео не применяются! Практически все видеоплееры/капчеры работают по изложенному мной принципу (взорви с помощью Dependency Walker какую-нибудь прогу типа Adobe Premiere и найди в списке импортируемых функций хоть какое-нибудь упоминание о таймерах!!!). И что, там закапченное видео проигрывается то быстрее, то медленнее?! Наоборот, батенька, данный подход обеспечивает ровное и непрерывное проигрывание/захват видео вне зависимости от загруженности системы, тем более можно сразу узнать сколько фреймов мы пропустили, если загруженность системы не позволила закапчить/воспроизвести несколько кадров, и как-то исправить сложившуюся ситуацию. Такой подход позволит максимально эффективно использовать производительность системы. А чтобы проц не загружать, можно использовать что-то типа

Код:
ElapsedTime = GetTickCount() - PrevTime;
    RequiredTime = 1000/fps;
    if (ElapsedTime < RequiredTime)
    {
        Sleep ((RequiredTime - ElapsedTime) / 2);
        return;
    }
    else
    {
        Капчим;
    Жмём;
        return;
    }

и всё...
2.4K
21 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Как уже было сказано Windows не является ОС реального времени, поэтому для точных интервалов времени следует использовать специализированные библиотеки, например DirectX


Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU

Ну и из предыдущих:

Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста

534
21 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by dinasok51
Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU

Ну и из предыдущих:

Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста



Да нету в DirectX таймеров. Но, зато в DirectShow есть интерфейс IReferenceClock и его метод GetTime(), возвращающий значение времени в 100 наносекундных единицах. Я с ним не работал, но 100 наносекундные интервалы заставляют призадуматься... Надо как-нибудь попробовать... На всякий случай приложу док по IReferenceClock, взятый из SDK

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU

Ну и из предыдущих:

Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста



В DirectX должны быть функции работы с временем.

Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by HarryAxe
Да нету в DirectX таймеров. Но, зато в DirectShow есть интерфейс IReferenceClock и его метод GetTime(), возвращающий значение времени в 100 наносекундных единицах. Я с ним не работал, но 100 наносекундные интервалы заставляют призадуматься... Надо как-нибудь попробовать... На всякий случай приложу док по IReferenceClock, взятый из SDK



А разве DirectShow не входит в DirectX ???

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by HarryAxe
НО, НАПОМИНАЮ, таймеры при работе с видео не применяются! Практически все видеоплееры/капчеры работают по изложенному мной принципу (взорви с помощью Dependency Walker какую-нибудь прогу типа Adobe Premiere и найди в списке импортируемых функций хоть какое-нибудь упоминание о таймерах!!!). И что, там закапченное видео проигрывается то быстрее, то медленнее?! Наоборот, батенька, данный подход обеспечивает ровное и непрерывное проигрывание/захват видео вне зависимости от загруженности системы, тем более можно сразу узнать сколько фреймов мы пропустили, если загруженность системы не позволила закапчить/воспроизвести несколько кадров, и как-то исправить сложившуюся ситуацию. Такой подход позволит максимально эффективно использовать производительность системы. А чтобы проц не загружать, можно использовать что-то типа
Код:
ElapsedTime = GetTickCount() - PrevTime;
    RequiredTime = 1000/fps;
    if (ElapsedTime < RequiredTime)
    {
        Sleep ((RequiredTime - ElapsedTime) / 2);
        return;
    }
    else
    {
        Капчим;
    Жмём;
        return;
    }

и всё...



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

534
22 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by AndreySar
А разве DirectShow не входит в DirectX ???


IReferenceClock - часы, а не таймер (хотя их тоже можно назвать таймером, но в этой теме речь идет о совершенно другой функциональности, как раз такой, специальных интерфейсов для которой DirectX не предоставляет)

534
22 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by AndreySar
Да, конечно именно так и следует делать, но только желательно использовать эту обработку в дочернем потоке, т.к. весь интерфейс программы "умрет".


А интерфейс не умрёт, потому что его не будет (автор хочет рипать содержимое экрана, а, значит, для него важна "чистота" рабочего стола). К тому же, основной поток заснёт не более чем на 40 миллисекунд

2.4K
22 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
В DirectX должны быть функции работы с временем.

Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.



Для начала, что ты называешь вызовом таймера?

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Для начала, что ты называешь вызовом таймера?



Вызов таймера - вызов предопределенной или переопределенной функции.

2.4K
22 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Вызов таймера - вызов предопределенной или переопределенной функции.



Хочешь ли ты сказать что напр. SetTimer может быть "пропущен"? При вызове какой функции у тебя очередь сообщений переполняется?

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Хочешь ли ты сказать что напр. SetTimer может быть "пропущен"? При вызове какой функции у тебя очередь сообщений переполняется?



После вызова SetTimer приложению постоянно посылаются сообщения WM_TIMER, до тех пор пока не будет вызван KillTimer или завершено приложение.
Если в течение определенного времени превышающий время посылки сообщения WM_TIMER функция-обработчик этого сообщения не успеет освободится повторный вызов этой функции не произойдет до тех пор пока она не освободится!!!

324
22 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
При вызове какой функции у тебя очередь сообщений переполняется?



В том то и дело что очередь не переполняется, т.к сообщения таймера не аккумулируются,

2.4K
22 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
После вызова SetTimer приложению постоянно посылаются сообщения WM_TIMER, до тех пор пока не будет вызван KillTimer или завершено приложение.
Если в течение определенного времени превышающий время посылки сообщения WM_TIMER функция-обработчик этого сообщения не успеет освободится повторный вызов этой функции не произойдет до тех пор пока она не освободится!!!


Это все правильно

А твои высказывания, процитированные ниже, пртиворечивы и не соответствуют действительности

Цитата:
Originally posted by AndreySar
В том то и дело что очередь не переполняется, т.к сообщения таймера не аккумулируются,



Все сообщения от таймера ставятся в очередь

Цитата:
Originally posted by AndreySar
.. вызовы ставятся в очередь сообщений, и если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.


Ставится

Цитата:
Originally posted by AndreySar
2. запросы не теряются, а пропускаются


Не пропускаются

Цитата:
Originally posted by AndreySar
Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.


Как ты это установил?


Цитата:
Originally posted by AndreySar

Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.



Пропусков никаких нет

1. В распоряжении 2GB и нужно сильно и долго стараться, чтобы это все заполонить
2. Если обработка сообщения от таймера в среднем длится дольше, чем период их поступления, то OS тут ни причем.

324
23 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51

Пропусков никаких нет

1. В распоряжении 2GB и нужно сильно и долго стараться, чтобы это все заполонить
2. Если обработка сообщения от таймера в среднем длится дольше, чем период их поступления, то OS тут ни причем.




Я могу столько послать сообщений таймера моему приложению, что ни одно другое сообщение не поступит!!!
Простой пример:
установи таймер на период t, в обработчике сообщений тамера загрузи его на время (t + Const);
убей свой таймер через время T, значительно превышаюшее время t,
по твоей логике должно обработаться (T / t1) сообщений от таймера, но их максимум обрабатывается только (T / (t + Const)) + 1;

2.4K
23 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
... в обработчике сообщений тамера загрузи его на время (t + Const);

Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?

Цитата:
Originally posted by AndreySar
... t1...


Что такое t1?

324
23 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?


Что такое t1?


Код:
SetTimer(1, 100, NULL);
SetTimer(2, 1000, NULL);

...
WM_TIMER:

//для 1 таймера
Sleep(200);
nCount++;

//для 2 таймера
KillTimer(1);
KillTimer(2);


через время 2000 смотришь значение nCount, оно равно у тебя 5, а не 10!!!
324
23 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?


Что такое t1?



Ты можешь сказать что нибудь по существу? или дальше будешь придираться к словам и приводить свои доводы по этому поводу?

2.4K
23 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Ты можешь сказать что нибудь по существу? или дальше будешь придираться к словам и приводить свои доводы по этому поводу?


Я тебя прошу уточнить,что это значит, для меня это выглядит неоднозначно.
И тогда я отвечу по существу.

2.4K
23 февраля 2006 года
dinasok51
219 / / 12.11.2005
Держи

"The DispatchMessage Windows function sends a WM_TIMER message when no other messages are in the application's message queue."

и на старуху бывает проруха
324
24 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Держи

"The DispatchMessage Windows function sends a WM_TIMER message when no other messages are in the application's message queue."

и на старуху бывает проруха



Я тебе говорю, что если в очереди сообщений находится уже одно сообщение от таймера, то ВТОРОЕ в очередь не ставится. А что ты хотел сказать этим, я не понял - действительно сообщение ставится в очередь сообщений приложения, но если в ней еще нет сообщений от этого таймера.

534
24 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by AndreySar
Я тебе говорю, что если в очереди сообщений находится уже одно сообщение от таймера, то ВТОРОЕ в очередь не ставится. А что ты хотел сказать этим, я не понял - действительно сообщение ставится в очередь сообщений приложения, но если в ней еще нет сообщений от этого таймера.


Не надо обсуждение проблемы точного тайминга переводить в бессмысленный спор о том, кто профи, а кто лох. Лучше бы по теме общались... The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. Это всем понятно? Переводить, надеюсь, не надо? Если таймер именно с накоплением надо, пользуй CreateTimerQueueTimer/DeleteTimerQueueTimer, в чём вопрос-то?

324
24 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by HarryAxe
Не надо обсуждение проблемы точного тайминга переводить в бессмысленный спор о том, кто профи, а кто лох. Лучше бы по теме общались... The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. Это всем понятно? Переводить, надеюсь, не надо? Если таймер именно с накоплением надо, пользуй CreateTimerQueueTimer/DeleteTimerQueueTimer, в чём вопрос-то?



Вообще то это все по теме, я пытался объяснить что с помощью WM_TIMER не получится сделать высокоточного таймера и следует использовать другие методы.

534
24 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by AndreySar
Вообще то это все по теме, я пытался объяснить что с помощью WM_TIMER не получится сделать высокоточного таймера и следует использовать другие методы.


Так с этого-то автор и начал тему. Вообще, как уже несколько раз было сказано, Windows - не есть операционная система реального времени, и организовать с большой точностью фызов функции с определённым периодом здесь НЕВОЗМОЖНО. Если так уж приспичило использовать именно такой метод планирования вызова кода, единственное, что можно посоветовать - SetTimer/CreateTimerQueueTimer + HIGH_PRIORITY_CLASS

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог