AIMP Forum

AIMP for Windows => Дополнения / Addons => Разработка / Development => Topic started by: Bytex on August 08, 2012, 16:58:07

Title: Как узнать текущую песню из стороннего приложения?
Post by: Bytex on August 08, 2012, 16:58:07
Как из AIMP'а можна вытянуть информацию про текущий проигруемый файл для использования в сторонней программе?
Тоесть трек переключился и информация в программе обновилась. Какие библиотеки надо использовать, функции и т.д.
Title: Re: Как узнать текущую песню?
Post by: Artem on August 08, 2012, 17:07:18
Качайте SDK (https://www.aimp.ru/index.php?do=download&cat=sdk), в каталоге для Delphi есть папка с демками, среди них есть демка AIMP_RemInfo.
Title: Re: Как узнать текущую песню?
Post by: Bytex on August 08, 2012, 17:51:34
Как быть в таком случае?

Code: [Select]
#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 []"


Если же поменять на
Code: [Select]
FAIMPWindow = FindWindow((LPCWSTR)AIMPRemoteAccessClass, (LPCWSTR)AIMPRemoteAccessClass);ничего не находит.

Все нашел:
Code: [Select]
FAIMPWindow = FindWindowA(AIMPRemoteAccessClass, AIMPRemoteAccessClass);
Title: Re: Как узнать текущую песню?
Post by: Bytex on August 08, 2012, 18:40:38
Проблема с получением версии AIMP:

Code: [Select]
int AIMPGetPropertyValue(int APropertyID)
{
if (FAIMPWindow)
return SendMessageW(FAIMPWindow, WM_AIMP_PROPERTY, APropertyID | AIMP_RA_PROPVALUE_GET, 0);
else
return 0;
}

но все время возвращает какоето число 20317232.

Полный код:
Code: [Select]
#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;
}
Title: Re: Как узнать текущую песню?
Post by: Artem on August 08, 2012, 19:48:37
В описании к AIMP_RA_PROPERTY_VERSION сказано:

Code: [Select]
  // Returns player version:
  // HiWord: Version ID (for example: 301 -> v3.01)
  // LoWord: Build Number
  AIMP_RA_PROPERTY_VERSION = $10;
Title: Re: Как узнать текущую песню?
Post by: Bytex on August 08, 2012, 19:58:20
дело в том что у меня не  20317232 версия, а в3.10, build 1072 и я точно не наблюдаю сдесь какогото сходства.

назначает свойства нормально, а вот с версией какието проблемы.
Title: Re: Как узнать текущую песню?
Post by: Artem on August 08, 2012, 20:11:27
Возьмите старшее и младшее слово возвращаемого int-а, что получится?
Получится HiWord = 310, LoWord = 1072
Title: Re: Как узнать текущую песню?
Post by: Bytex on August 09, 2012, 00:03:36
Code: [Select]
// 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.
Что делать???
Title: Re: Как узнать текущую песню?
Post by: Artem on August 09, 2012, 08:28:04
Вы смотрели демку? Видели как там реализовано?
Title: Re: Как узнать текущую песню?
Post by: Bytex on August 09, 2012, 11:54:09
В общем вот реализация на C++:
Code: [Select]
#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;
}
Title: Re: Как узнать текущую песню?
Post by: Artem on August 09, 2012, 11:55:50
угу, как-то так и должно быть.
Title: Re: Как узнать текущую песню?
Post by: Gogich on September 24, 2012, 16:22:46
У меня небольшой вопрос. Ситуация такая, есть тип TAIMPFileInfo:
Code: [Select]
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
Code: [Select]
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, то могу вызывать функцию следующим образом:
Code: [Select]
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.

Сейчас поколдую, конечно, но честно, даже не догадываюсь, в чем может быть ошибка.
Title: Re: Как узнать текущую песню?
Post by: Artem on September 24, 2012, 16:30:58
В чем может быть ошибка? Плеер однозначно инициализирован. Так как трек переключается. А вот почему не хочет отдавать/принимать FileInfo я не понимаю. Дебаггером пользоваться не умею, всё время работал с C# и Java.

Серьезно, вы никогда в жизни не пользовались отладчиком? Я вам завидую... (может мне стоит перестать писать по ночам?).

К делу. Проблема тут кроется в том, что вы не заполнили структуру FileInfo, а именно - указатели на буферы, куда плеер будет помещать данные. Посмотрите, как реализован класс-обертка FileInfoAdapter.
Title: Re: Как узнать текущую песню?
Post by: Gogich on September 24, 2012, 16:43:33
О, спасибо. Понял. Я, кстати, заметил, что что-то нужно в этом направлении сделать.. А файл этот с описанием TAIMPFileInfoAdapter просто не нашел)))

__

Нет, отладчик там есть, но он совсем по-другому устроен. Тебе не нужно смотреть код ассемблера и значения ячеек в памяти, все это делает за тебе MS Visual Studio. Все, что ты делаешь - ставишь breakpoint'ы, нажимаешь "Старт" (либо присоединиться к процессу, если речь идет о dll) и среда останавливается, показывает сразу значения переменных, условных операторов, и прочее. Более человечно все-таки, я считаю. Может даже иногда показать, где допущена ошибка. А анализатор кода настолько мощный, то сразу все возможные неприятности расскажет и покажет.
Title: Re: Как узнать текущую песню?
Post by: Artem on September 24, 2012, 16:54:12
Нет, отладчик там есть, но он совсем по-другому устроен. Тебе не нужно смотреть код ассемблера и значения ячеек в памяти, все это делает за тебе MS Visual Studio. Все, что ты делаешь - ставишь breakpoint'ы, нажимаешь "Старт" (либо присоединиться к процессу, если речь идет о dll) и среда останавливается, показывает сразу значения переменных, условных операторов, и прочее. Более человечно все-таки, я считаю. Может даже иногда показать, где допущена ошибка. А анализатор кода настолько мощный, то сразу все возможные неприятности расскажет и покажет.

Аналогично работает и дельфи.