AIMP Forum
AIMP for Windows => Дополнения / Addons => Разработка / Development => Topic started by: HardWareMan on March 07, 2008, 09:42:35
-
Появилось время и я захотел доработать свой визуальный плагин LumaVU. Собственно, он работает, просто из-за постоянной перерисовки заднего фона он иногда мерцает. Пытаюсь решить эту проблему. Попробовал подключить 2 поверхность, рисовать в ней а потом зараз копировать готовое изображение в главный холст. Но что-то не получается. Ну или как вариант залочить канвас на время отрисовки...
Собственна, имею следующие вопросы:
1. Можно ли подключить дополнительные поверхности для уменьшения лишних перерисовок? Если да, то как?
2. Есть ли метод или функция, однозначно лочившая главный холст?
Так же интересно, как сам плеер считывает данные с холста для отрисовки или отрисовка происходит в холст плеера напрямую?
-
в таких случаях, когда нельзя избавиться от фликов (мерцаний) другим способом, используют двойную буфферизацию, т.е. сначала рисуют все полностью на внутреннем буфере (на Bitmapе, как правило), а потом выводят готовое изображение на DC.
Вот небольшой пример:
procedure DisplayRender(DC: HDC; AData: PVisualData); stdcall;
var
ABitmap: TBitmap;
begin
ABitmap := TBitmap.Create; // создаем внутренний буфер
try
ABitmap.Width := W;
ABitmap.height := H; // размеры дисплея приходят на Resize
Paint(ABitmap.Canvas.Handle, AData); // наша внутренняя отрисовка
BitBlt(DC, 0, 0, W, H, ABitmap.Canvas.Handle, 0, 0, SRCCOPY); // Выводим с буфера на дисплей
finally
ABitmap.Free;
end;
end;
P.S. По-хорошему, в нашем случае, лучше будет так поступить:
+ буфер создавать и убивать при создании / дестрое плагина (чтобы при отрисовке каждый раз это не делать)
+ Ресайзить буфер при вызове функции Resize, которая передает координаты
Забыл:
>>ак же интересно, как сам плеер считывает данные с холста для отрисовки или отрисовка происходит в холст плеера напрямую?
2-ая буферизация используется только для полноэкранного режима
-
в таких случаях, когда нельзя избавиться от фликов (мерцаний) другим способом, используют двойную буфферизацию, т.е. сначала рисуют все полностью на внутреннем буфере (на Bitmapе, как правило), а потом выводят готовое изображение на DC.
Вот небольшой пример:
procedure DisplayRender(DC: HDC; AData: PVisualData); stdcall;
var
ABitmap: TBitmap;
begin
ABitmap := TBitmap.Create; // создаем внутренний буфер
try
ABitmap.Width := W;
ABitmap.height := H; // размеры дисплея приходят на Resize
Paint(ABitmap.Canvas.Handle, AData); // наша внутренняя отрисовка
BitBlt(DC, 0, 0, W, H, ABitmap.Canvas.Handle, 0, 0, SRCCOPY); // Выводим с буфера на дисплей
finally
ABitmap.Free;
end;
end;
О, это должно проканать, ато я пытался TCanvas намутить и ничего не получалось...
P.S. По-хорошему, в нашем случае, лучше будет так поступить:
+ буфер создавать и убивать при создании / дестрое плагина (чтобы при отрисовке каждый раз это не делать)
+ Ресайзить буфер при вызове функции Resize, которая передает координаты
Угу, так и делаем.
Забыл:
>>ак же интересно, как сам плеер считывает данные с холста для отрисовки или отрисовка происходит в холст плеера напрямую?
2-ая буферизация используется только для полноэкранного режима
Вот почему в фулскрине не мигает... ;)
-
Вот поправил и избавился от мерцания! Теперь осталось проработать полноэкранный режим и все!
Забирать здесь (http://webfile.ru/1795228).
-
ребята помогите, я связался с разработчиком Winamp Wrapper (здесь писал об этом плагине https://www.aimp.ru/forum/index.php?topic=3730.0) и он говорит что ему нужен пример плагина визуализации для создания аналогичного плагина для AIMP, запостите в этой теме, он прочитает
вот что он пишет:
The AIMP_Vis_Demo posted on https://www.aimp.ru/forum/index.php?topic=1733.0 by Spir1tus doesn't work here. Maybe it is for an old AIMP version.
I tried it by writing a main addon with the C++ example as base from the same topic (posted by Artem) but there is no way to get the wave form data needed for visualisation that way.
Then I tried to copy the visualisation plugin definitions from the Delphi SDK, but I was only able to crash AIMP after loading my test plugin.
-
>>>Then I tried to copy the visualisation plugin definitions from the Delphi SDK, but I was only able to crash AIMP after loading my test plugin
Если возможно, пусть даст посмотреть плагин / часть, где он переносил код из дельфи, попробую выявить причину падения.
-
Here's my test code in a short form:
#include "windows.h"
#define VIS_RQD_DATA_WAVE 1
#define VIS_RQD_DATA_SPECTRUM 2
#define VIS_RQD_NOT_SUSPEND 4
typedef char TWaveForm[2][512];
typedef BYTE TSpectrum[2][256];
typedef struct { BYTE LevelR, LevelL; TWaveForm Waveform; TSpectrum Spectrum; }TVisData, *PVisData;
typedef struct
{
//BYTE Version;
//DWORD DllInstance;
PWCHAR (__stdcall *Author)();
PWCHAR (__stdcall *PluginName)();
PWCHAR (__stdcall *PluginInfo)();
DWORD (__stdcall *PluginFlags)();
BOOL (__stdcall *Initialize)();
void (__stdcall *Deinit)();
void (__stdcall *DisplayClicked)(int x, int y);
void (__stdcall *DisplayRender)(HDC Canvas, PVisData pVD );
void (__stdcall *DisplayResize)(int NewW, int NewH );
}TAIMP2VisualPlugin, *PAIMP2VisualPlugin;
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
PWCHAR __stdcall Author() { return L"Test Author"; }
PWCHAR __stdcall PluginName() { return L"Test Visual Plugin"; }
PWCHAR __stdcall PluginInfo() { return L""; }
DWORD __stdcall PluginFlags() { return VIS_RQD_DATA_WAVE|VIS_RQD_DATA_SPECTRUM|VIS_RQD_NOT_SUSPEND; }
void __stdcall Resize(int NewW, int NewH ) { }
void __stdcall Render(HDC Canvas, PVisData pVD ) { }
void __stdcall Deinit() { }
void __stdcall Clicked(int x, int y) { }
BOOL __stdcall Initialize();
TAIMP2VisualPlugin plugin =
{
//1/*PLUGIN_VERSION*/,
//0,
Author,
PluginName,
PluginInfo,
PluginFlags,
Initialize,
Deinit,
Clicked,
Render,
Resize,
};
extern "C" __declspec( dllexport ) PAIMP2VisualPlugin AIMP_QueryVisual()
{
MessageBox(NULL, L"AIMP_QueryVisual", L"", 0);
return &plugin;
}
BOOL __stdcall Initialize()
{
MessageBoxW(NULL, L"Initialize", L"",0);
return TRUE;
}
-
Hm, You conversion is invalid, IAIMP2VisualPlugin is not a struct, is interface.
Interfaces declarate as (for example):
class IAIMPClassicPlayer
: public IUnknown
{
public:
virtual int __stdcall Version() = 0;
virtual boolean __stdcall PlayTrack(HPLS APlaylistID, int ATrackID) = 0;
virtual void __stdcall PlayOrResume() = 0;
virtual void __stdcall Pause() = 0;
virtual void __stdcall Stop() = 0;
virtual void __stdcall NextTrack() = 0;
virtual void __stdcall PrevTrack() = 0;
};
-
hmm, the best thing I could come up with is the following, which still crashes AIMP the same way:
#include "windows.h"
#define VIS_RQD_DATA_WAVE 1
#define VIS_RQD_DATA_SPECTRUM 2
#define VIS_RQD_NOT_SUSPEND 4
typedef char TWaveForm[2][512];
typedef BYTE TSpectrum[2][256];
typedef struct { BYTE LevelR, LevelL; TWaveForm Waveform; TSpectrum Spectrum; } TVisData, *PVisData;
class IAIMP2VisualPlugin : public IUnknown
{
public:
virtual PWCHAR __stdcall AuthorName() = 0;
virtual PWCHAR __stdcall PluginName() = 0;
virtual PWCHAR __stdcall PluginInfo() = 0;
virtual DWORD __stdcall PluginFlags() = 0;
virtual boolean __stdcall Initialize() = 0;
virtual void __stdcall Deinitialize() = 0;
virtual void __stdcall DisplayClick(int x, int y) = 0;
virtual void __stdcall DisplayRender(HDC Canvas, PVisData pVD) = 0;
virtual void __stdcall DisplayResize(int NewW, int NewH) = 0;
long __stdcall QueryInterface(const struct _GUID &,void ** )
{ MessageBoxW(NULL, L"IAIMP2VisualPlugin::QueryInterface", L"",0); return 1; }
unsigned long __stdcall AddRef(void)
{ MessageBoxW(NULL, L"IAIMP2VisualPlugin::AddRef", L"",0); return 1; }
unsigned long __stdcall Release(void)
{ MessageBoxW(NULL, L"IAIMP2VisualPlugin::Release", L"",0); return 1; }
long __stdcall CreateInstance(struct IUnknown *,const struct _GUID &,void ** )
{ MessageBoxW(NULL, L"IAIMP2VisualPlugin::CreateInstance", L"",0); return 1; }
long __stdcall LockServer(int)
{ MessageBoxW(NULL, L"IAIMP2VisualPlugin::LockServer", L"",0); return 1; }
};
class TAIMP2VisualPlugin : public IAIMP2VisualPlugin
{
public:
PWCHAR __stdcall AuthorName() { return L"Test Author"; }
PWCHAR __stdcall PluginName() { return L"Test Visual Plugin"; }
PWCHAR __stdcall PluginInfo() { return L""; }
DWORD __stdcall PluginFlags() { return VIS_RQD_DATA_WAVE|VIS_RQD_DATA_SPECTRUM|VIS_RQD_NOT_SUSPEND; }
boolean __stdcall Initialize() { MessageBoxW(NULL, L"Initialize", L"",0); return TRUE; }
void __stdcall Deinitialize() { }
void __stdcall DisplayClick(int x, int y) { }
void __stdcall DisplayRender(HDC Canvas, PVisData pVD ) { }
void __stdcall DisplayResize(int NewW, int NewH ) { }
} VisualPlugin;
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
extern "C" __declspec( dllexport ) IAIMP2VisualPlugin* AIMP_QueryVisual()
{
MessageBox(NULL, L"AIMP_QueryVisual", L"", 0);
return &VisualPlugin;
}
As you can see, I don't have the slightest clue about COM programming... So I guess I need to wait until I can get a working C++ example of a visual plugin for AIMP. The only way so far for me with C++ seems to be Sonique plugin, unfortunately I need support for at least the DisplayClick function (which is available in Sonique Plugin API but not called/supported by AIMP). Plus actual usage of the AIMP2 API via IAIMP2Controller would be useful.
Maybe Spir1tus can post a working version of AIMP_Vis_Demo.rar from https://www.aimp.ru/forum/index.php?topic=1733.0 ?
-
See at attach the demo project (originally by Spir1tus with my correction)
-
Thanks, got something working now. Should be able to release a first version soon.
Short question, is there a way to get a IAIMP2Controller or something like that?
For now I use the Winamp emulation provided by AIMP's own "Winamp v1.x" window. A lot of stuff works already anyway, so it's not too urgent :-)
-
Отличная визуализация! +1. Напомнила старенький "Маяк" :)
Правда не во всех скинах нормально работает... :(
1. Это не Маяковый лума, а Радиотехнический.
2. Знаю, это вообще был тестовый проект. Шрифт средствами канваса нельзя написать, поэтому при других аспектах он косячит.
Я хочу попробовать отрендерить на еще одну поверхность шрифты и разметку в статический рисунок и потом переносить масштабированно (будет растягивать и т.д., но будет красиво). Так же, есть план занести туда изображения всех экранчиков Маяка (их всего 3) и добавить экранчик магнитофона Радиотехники (текущий - с усила, от мафона со счетчиком).
-
1. Это не Маяковый лума, а Радиотехнический.
Вообще подобные "экранчики" были на многих советских магниофонах: "Юпитер","Маяк","Орель","Яуза","Радиотехника","Электроника"и т.д. В большинстве своем они идентичные, так что определить с какого ты рисовал невозможно :)
-
Вообще подобные "экранчики" были на многих советских магниофонах: "Юпитер","Маяк","Орель","Яуза","Радиотехника","Электроника"и т.д. В большинстве своем они идентичные, так что определить с какого ты рисовал невозможно :)
Согласен, но маяковский длинный. Очень длинный. %) А конкретный этот я рисовал с усилка радиотехнического, коим и пользуюсь до сих пор (естественно прокачав некоторые параметры ;)).
-
Вопрос как раз о тонкости.
В окне плагинов, в списке "Подключенные плагины", есть кнопочка "Настройки".
Подскажите, что в коде Delphi замутить, чтобы можно было кликнуть эту кнопку и получить доступ к настройкам плагина. Поискал в SDK, но сходу не нашёл.
Нужен просто пример для зацепки, в остальном разберусь.
-
Подскажите, что в коде Delphi замутить, чтобы можно было кликнуть эту кнопку и получить доступ к настройкам плагина.
Эта кнопка не действует для визуальных плагинов.
-
Зато для них отлично действует клик по дисплею.