AIMP Forum
AIMP for Windows => Дополнения / Addons => Разработка / Development => Topic started by: Bytex on August 08, 2012, 16:58:07
-
Как из AIMP'а можна вытянуть информацию про текущий проигруемый файл для использования в сторонней программе?
Тоесть трек переключился и информация в программе обновилась. Какие библиотеки надо использовать, функции и т.д.
-
Качайте SDK (https://www.aimp.ru/index.php?do=download&cat=sdk), в каталоге для Delphi есть папка с демками, среди них есть демка AIMP_RemInfo.
-
Как быть в таком случае?
#include "stdafx.h"
#include "AIMPSDKCommon.h"
#include "AIMPSDKRemote.h"
#include <conio.h>
#include <iostream>
using namespace std;
HWND FAIMPWindow;
int _tmain(int argc, _TCHAR* argv[])
{
FAIMPWindow = FindWindow(AIMPRemoteAccessClass, AIMPRemoteAccessClass);
if (!FAIMPWindow)
cout<<"No";
else
cout<<"Yes";
_getch();
return 0;
}
Компилятор ругается: error C2440: инициализация: невозможно преобразовать "const char [17]" в "const LPCWSTR []"
Если же поменять на FAIMPWindow = FindWindow((LPCWSTR)AIMPRemoteAccessClass, (LPCWSTR)AIMPRemoteAccessClass);
ничего не находит.
Все нашел:
FAIMPWindow = FindWindowA(AIMPRemoteAccessClass, AIMPRemoteAccessClass);
-
Проблема с получением версии AIMP:
int AIMPGetPropertyValue(int APropertyID)
{
if (FAIMPWindow)
return SendMessageW(FAIMPWindow, WM_AIMP_PROPERTY, APropertyID | AIMP_RA_PROPVALUE_GET, 0);
else
return 0;
}
но все время возвращает какоето число 20317232.
Полный код:
#include "stdafx.h"
#include "AIMPSDKCommon.h"
#include "AIMPSDKRemote.h"
#include <conio.h>
#include <iostream>
using namespace std;
HWND FAIMPWindow; //AIMP
int AVersion; //Version
int AIMPGetPropertyValue(int);
int _tmain(int argc, _TCHAR* argv[])
{
//Find AIMP
FAIMPWindow = FindWindowA(AIMPRemoteAccessClass, AIMPRemoteAccessClass);
if (FAIMPWindow)
{
AVersion = AIMPGetPropertyValue(AIMP_RA_PROPERTY_VERSION);
cout<<AVersion;
}
else cout<<"AIMP not running";
_getch();
return 0;
}
int AIMPGetPropertyValue(int APropertyID)
{
if (FAIMPWindow)
return SendMessageW(FAIMPWindow, WM_AIMP_PROPERTY, APropertyID | AIMP_RA_PROPVALUE_GET, 0);
else
return 0;
}
-
В описании к AIMP_RA_PROPERTY_VERSION сказано:
// Returns player version:
// HiWord: Version ID (for example: 301 -> v3.01)
// LoWord: Build Number
AIMP_RA_PROPERTY_VERSION = $10;
-
дело в том что у меня не 20317232 версия, а в3.10, build 1072 и я точно не наблюдаю сдесь какогото сходства.
назначает свойства нормально, а вот с версией какието проблемы.
-
Возьмите старшее и младшее слово возвращаемого int-а, что получится?
Получится HiWord = 310, LoWord = 1072
-
// AIMPvvv.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include "AIMPSDKCommon.h"
#include "AIMPSDKRemote.h"
#include <conio.h>
#include <iostream>
#include <limits>
using namespace std;
HWND FAIMPWindow; //AIMP
DWORD AVersion; //Version
int AIMPGetPropertyValue(int);
bool AIMPSetPropertyValue(int , int);
int _tmain(int argc, _TCHAR* argv[])
{
//Find AIMP
FAIMPWindow = FindWindowA(AIMPRemoteAccessClass, AIMPRemoteAccessClass);
if (FAIMPWindow)
{
//AVersion = AIMPGetPropertyValue(AIMP_RA_PROPERTY_VERSION);
//cout<<((AVersion & 0x00FF)|(AVersion & 0xFF00));
HANDLE AFile;
HANDLE _AInfo;
TAIMPFileInfo *AInfo;
string S;
string ABuf;
AFile = OpenFileMappingA(FILE_MAP_READ, TRUE, AIMPRemoteAccessClass);
_AInfo = MapViewOfFile(AFile, FILE_MAP_READ, 0, 0, AIMPRemoteAccessMapFileSize);
AInfo = (TAIMPFileInfo*)_AInfo;
cout<<AInfo->FileSize<<endl;
cout<<AInfo->BitRate<<endl;
cout<<AInfo->Artist;
}
else cout<<"AIMP not running";
_getch();
return 0;
}
int AIMPGetPropertyValue(int APropertyID)
{
if (FAIMPWindow)
return SendMessage(FAIMPWindow, WM_AIMP_PROPERTY, APropertyID | AIMP_RA_PROPVALUE_GET, 0);
else
return 0;
}
bool AIMPSetPropertyValue(int APropertyID, int AValue)
{
if(FAIMPWindow)
return SendMessage(FAIMPWindow, WM_AIMP_PROPERTY, APropertyID | AIMP_RA_PROPVALUE_SET, AValue);
else
return false;
}
В общем битрейт и размер файла уже выводит, но например артиста и любую информацию PWCHAR выводит 000000.
Что делать???
-
Вы смотрели демку? Видели как там реализовано?
-
В общем вот реализация на C++:
#include <Windows.h>
#include <stdio.h>
#define AIMP2_RemoteClass L"AIMP2_RemoteInfo"
#define AIMP2_RemoteClassSize 2048
#pragma pack(push, 1)
typedef struct _AIMP2FileInfo
{
DWORD cbSizeOf;
//
BOOL nActive;
DWORD nBitRate;
DWORD nChannels;
DWORD nDuration;
INT64 nFileSize;
DWORD nRating;
DWORD nSampleRate;
DWORD nTrackID;
//
DWORD nAlbumLen;
DWORD nArtistLen;
DWORD nDateLen;
DWORD nFileNameLen;
DWORD nGenreLen;
DWORD nTitleLen;
//
PWCHAR sAlbum;
PWCHAR sArtist;
PWCHAR sDate;
PWCHAR sFileName;
PWCHAR sGenre;
PWCHAR sTitle;
} AIMP2FileInfo, *PAIMP2FileInfo;
#pragma pack(pop)
int __cdecl
wmain()
{
HANDLE hAIMP;
PAIMP2FileInfo aimpFileInfo;
LPWSTR pBuff;
hAIMP = OpenFileMapping(FILE_MAP_READ, FALSE, AIMP2_RemoteClass);
if ( !hAIMP )
{
wprintf(L"error %d\r\n", GetLastError());
return 1;
}
aimpFileInfo = (PAIMP2FileInfo)MapViewOfFile(hAIMP, FILE_MAP_READ, 0, 0, AIMP2_RemoteClassSize);
if ( aimpFileInfo )
{
WCHAR buff[256];
#define WRITE_TO_BUFF(x) \
memcpy(buff, pBuff, (x) * 2); \
buff[x] = '\0'; \
pBuff += (x);
// В pBuff вся остальная информация, разбивайте её испольуя поля nAlbumLen (и т.п.)
// из структуры aimpFileInfo
pBuff = (LPWSTR)((PBYTE)aimpFileInfo + aimpFileInfo->cbSizeOf);
wprintf(L"%d Hz, %d kbps, %d chans\r\n", aimpFileInfo->nSampleRate, aimpFileInfo->nBitRate, aimpFileInfo->nChannels);
wprintf(L"%d seconds, %d bytes\r\n", aimpFileInfo->nDuration / 1000, aimpFileInfo->nFileSize);
WRITE_TO_BUFF(aimpFileInfo->nAlbumLen)
wprintf(L"Album: %s\r\n", buff);
WRITE_TO_BUFF(aimpFileInfo->nArtistLen)
wprintf(L"Artist: %s\r\n", buff);
WRITE_TO_BUFF(aimpFileInfo->nDateLen)
wprintf(L"Date: %s\r\n", buff);
WRITE_TO_BUFF(aimpFileInfo->nFileNameLen)
wprintf(L"File name: %s\r\n", buff);
WRITE_TO_BUFF(aimpFileInfo->nGenreLen)
wprintf(L"Genre: %s\r\n", buff);
WRITE_TO_BUFF(aimpFileInfo->nTitleLen)
wprintf(L"Title: %s\r\n", buff);
UnmapViewOfFile(aimpFileInfo);
}
CloseHandle(hAIMP);
system("pause");
return 0;
}
-
угу, как-то так и должно быть.
-
У меня небольшой вопрос. Ситуация такая, есть тип TAIMPFileInfo:
type
PAIMPFileInfo = ^TAIMPFileInfo;
TAIMPFileInfo = packed record
StructSize: DWORD; // SizeOf(TAIMPFileInfo)
//
Active: LongBool;
BitRate: DWORD;
Channels: DWORD;
Duration: DWORD;
FileSize: Int64;
Mark: DWORD;
SampleRate: DWORD;
TrackNumber: DWORD;
//
AlbumLength: DWORD;
ArtistLength: DWORD;
DateLength: DWORD;
FileNameLength: DWORD;
GenreLength: DWORD;
TitleLength: DWORD;
//
Album: PWideChar;
Artist: PWideChar;
Date: PWideChar;
FileName: PWideChar;
Genre: PWideChar;
Title: PWideChar;
end;
Есть интерфейс IAIMPAddonsPlayerManager
IAIMPAddonsPlayerManager = interface(IUnknown)
[SID_IAIMPAddonsPlayerManager]
function PlayEntry(AEntry: HPLSENTRY): HRESULT; stdcall;
function PlayFile(AFileName: PWideChar; AFailIfNotExistsInPlaylist: LongBool): HRESULT; stdcall;
function PlayStorage(ID: HPLS; AEntryIndex: Integer = -1): HRESULT; stdcall;
// Register / Unregister custom FileInfo repository, you can put own info about the any file
function FileInfoRepository(ARepository: IAIMPAddonsFileInfoRepository; ARegister: LongBool): HRESULT; stdcall;
// if AFileName = nil: Get information about currently playing file
function FileInfoQuery(AFileName: PWideChar; AInfo: PAIMPFileInfo): HRESULT; stdcall;
// Register / Unregister custom playing queue controller
function PlayingQueueController(AController: IAIMPAddonsPlayingQueueController; ARegister: LongBool): HRESULT; stdcall;
// see AIMP_CFG_PATH_XXX
function ConfigGetPath(AConfigPathID: Integer; ABuffer: PWideChar; ABufferSizeInChars: Integer): HRESULT; stdcall;
// see AIMP_SUPPORTS_EXTS_XXX
function SupportsExts(AFlags: DWORD; ABuffer: PWideChar; ABufferSizeInChars: Integer): HRESULT; stdcall;
end;
Больше всего меня интересует функция FileInfoQuery, которая заполняет информацией экземпляр TAIMPFileInfo по переданной ссылке, если первый параметр её равен nil. То есть, после того, как я инициализировал AIMPPlayerManager, то могу вызывать функцию следующим образом:
var
finfo: TAIMPFileInfo;
i: longbool;
begin
ZeroMemory(@fInfo, SizeOf(fInfo)); // Не уверен, правильно ли это?
fInfo.StructSize := SizeOf(fInfo); // И вот это
i := false;
if AUserData.FFrame.PlayerManager <> nil then
AUserData.FFrame.PlayerManager.PlayFile('D:\Downloads\Музыка\e84df0f642a5.mp3', i); // Трек переключается => плеер инициализирован
try
if Succeeded(AUserData.FFrame.PlayerManager.FileInfoQuery(nil, @fInfo)) then // Возвращает false
begin
MessageBox(0, fInfo.Artist, fInfo.Title, MB_OK);
{Plugin.SendInfo( //Чисто моя функция
FileInfo.Artist,
FileInfo.Title,
FileInfo.Genre,
); }
end
else
MessageBox(0, 'not Succeeded', ' ', 0);
except
on E : Exception do
MessageBox(0, PWideChar(E.Message), PWideChar(E.ClassName), MB_OK);
end;
В чем может быть ошибка? Плеер однозначно инициализирован. Так как трек переключается. А вот почему не хочет отдавать/принимать FileInfo я не понимаю. Дебаггером пользоваться не умею, всё время работал с C# и Java.
Сейчас поколдую, конечно, но честно, даже не догадываюсь, в чем может быть ошибка.
-
В чем может быть ошибка? Плеер однозначно инициализирован. Так как трек переключается. А вот почему не хочет отдавать/принимать FileInfo я не понимаю. Дебаггером пользоваться не умею, всё время работал с C# и Java.
Серьезно, вы никогда в жизни не пользовались отладчиком? Я вам завидую... (может мне стоит перестать писать по ночам?).
К делу. Проблема тут кроется в том, что вы не заполнили структуру FileInfo, а именно - указатели на буферы, куда плеер будет помещать данные. Посмотрите, как реализован класс-обертка FileInfoAdapter.
-
О, спасибо. Понял. Я, кстати, заметил, что что-то нужно в этом направлении сделать.. А файл этот с описанием TAIMPFileInfoAdapter просто не нашел)))
__
Нет, отладчик там есть, но он совсем по-другому устроен. Тебе не нужно смотреть код ассемблера и значения ячеек в памяти, все это делает за тебе MS Visual Studio. Все, что ты делаешь - ставишь breakpoint'ы, нажимаешь "Старт" (либо присоединиться к процессу, если речь идет о dll) и среда останавливается, показывает сразу значения переменных, условных операторов, и прочее. Более человечно все-таки, я считаю. Может даже иногда показать, где допущена ошибка. А анализатор кода настолько мощный, то сразу все возможные неприятности расскажет и покажет.
-
Нет, отладчик там есть, но он совсем по-другому устроен. Тебе не нужно смотреть код ассемблера и значения ячеек в памяти, все это делает за тебе MS Visual Studio. Все, что ты делаешь - ставишь breakpoint'ы, нажимаешь "Старт" (либо присоединиться к процессу, если речь идет о dll) и среда останавливается, показывает сразу значения переменных, условных операторов, и прочее. Более человечно все-таки, я считаю. Может даже иногда показать, где допущена ошибка. А анализатор кода настолько мощный, то сразу все возможные неприятности расскажет и покажет.
Аналогично работает и дельфи.