d-anmusic/source/aimpremote/aimpremote.d

180 lines
5.1 KiB
D
Raw Normal View History

2017-08-29 09:19:28 +03:00
module aimpremote;
import core.sys.windows.windows;
import std.typecons : Nullable;
2017-08-29 09:19:28 +03:00
private const wstring AIMPRemoteAccessClass = "AIMP2_RemoteInfo";
private const int AIMPRemoteAccessMapFileSize = 2048;
align(1)
private struct AIMPRemoteFileInfo
{
DWORD deprecated1;
BOOL active;
DWORD bitRate;
DWORD channels;
DWORD duration;
align(4) INT64 fileSize;
DWORD fileMark;
DWORD sampleRate;
DWORD trackNumber;
DWORD albumLength;
DWORD artistLength;
DWORD dateLength;
DWORD fileNameLength;
DWORD genreLength;
DWORD titleLength;
DWORD[6] deprecated2;
};
private const int WM_AIMP_COMMAND = WM_USER + 0x75;
private const int WM_AIMP_NOTIFY = WM_USER + 0x76;
private const int WM_AIMP_PROPERTY = WM_USER + 0x77;
private const int AIMP_RA_PROPVALUE_GET = 0;
private const int AIMP_RA_PROPVALUE_SET = 1;
private const int AIMP_RA_PROPERTY_MASK = 0xFFFFFFF0;
private const int AIMP_RA_PROPERTY_PLAYER_STATE = 0x40;
private const int AIMP_RA_PROPERTY_VOLUME = 0x50;
private const int AIMP_RA_CMD_BASE = 10;
private const int AIMP_RA_CMD_NEXT = AIMP_RA_CMD_BASE + 7;
private const int AIMP_RA_CMD_PREV = AIMP_RA_CMD_BASE + 8;
2017-08-29 09:19:28 +03:00
private enum TagItem {
Album, Artist, Date, FileName, Genre, Title
}
public struct TrackInfo {
wstring artist;
wstring title;
wstring genre;
};
public enum PlayerState {
Off, Stopped, Paused, Playing
}
public static PlayerState getPlayerState() {
auto hwnd = findPlayerWindow();
if (hwnd == null) {
return PlayerState.Off;
}
const auto state = SendMessage(hwnd, WM_AIMP_PROPERTY,
AIMP_RA_PROPERTY_PLAYER_STATE | AIMP_RA_PROPVALUE_GET, 0);
switch (state) {
default: return PlayerState.Stopped;
case 1: return PlayerState.Paused;
case 2: return PlayerState.Playing;
}
}
public static void setVolume(ubyte volume) {
auto hwnd = findPlayerWindow();
if (hwnd != null) {
SendMessage(hwnd, WM_AIMP_PROPERTY,
AIMP_RA_PROPERTY_VOLUME | AIMP_RA_PROPVALUE_SET, volume);
}
}
public static void nextTrack() {
auto hwnd = findPlayerWindow();
if (hwnd != null) {
SendMessage(hwnd, WM_AIMP_COMMAND, AIMP_RA_CMD_NEXT, 0);
}
}
public static Nullable!TrackInfo getInfo() {
2017-08-29 09:19:28 +03:00
import std.conv : to;
import std.traits : EnumMembers;
Nullable!TrackInfo result = Nullable!TrackInfo.init;
2017-08-29 09:19:28 +03:00
auto haimp = OpenFileMapping(FILE_MAP_READ, 0, AIMPRemoteAccessClass.ptr);
if (haimp == null) {
result.nullify();
return result;
}
2017-08-29 09:19:28 +03:00
const auto hfilemap = MapViewOfFile(haimp, FILE_MAP_READ, 0, 0, AIMPRemoteAccessMapFileSize);
if (hfilemap == null) {
result.nullify();
return result;
}
2017-08-29 09:19:28 +03:00
AIMPRemoteFileInfo* info = cast(AIMPRemoteFileInfo*) hfilemap;
auto bytes = (cast(ubyte*) hfilemap)[0 .. AIMPRemoteAccessMapFileSize];
const wcharsize = wchar.sizeof;
auto pbuff = AIMPRemoteFileInfo.sizeof;
DWORD[TagItem] lengthInfo;
wstring[TagItem] trackInfo;
lengthInfo[TagItem.Album] = info.albumLength;
lengthInfo[TagItem.Artist] = info.artistLength;
lengthInfo[TagItem.Date] = info.dateLength;
lengthInfo[TagItem.FileName] = info.fileNameLength;
lengthInfo[TagItem.Genre] = info.genreLength;
lengthInfo[TagItem.Title] = info.titleLength;
foreach (index, immutable item; [EnumMembers!TagItem]) {
auto key = to!TagItem(index);
auto length = lengthInfo[key];
trackInfo[key] = cast(wstring)(bytes[pbuff .. (pbuff + length * wcharsize)]);
pbuff += length * wcharsize;
}
TrackInfo r = {
2017-08-29 09:19:28 +03:00
artist: trackInfo[TagItem.Artist],
title: trackInfo[TagItem.Title],
genre: trackInfo[TagItem.Genre]
};
result = Nullable!TrackInfo(r);
2017-08-29 09:19:28 +03:00
return result;
}
private static HWND findPlayerWindow() {
return FindWindow(AIMPRemoteAccessClass.ptr, null);
}
/*void main() {
import std.stdio : writeln, write;
auto haimp = OpenFileMapping(FILE_MAP_READ, 0, AIMPRemoteAccessClass.ptr);
auto hfilemap = MapViewOfFile(haimp, FILE_MAP_READ, 0, 0, AIMPRemoteAccessMapFileSize);
AIMPRemoteFileInfo* info = cast(AIMPRemoteFileInfo*) hfilemap;
write("Bitrate: ");
writeln(info.bitRate);
write("Samlerate: ");
2017-08-29 09:19:28 +03:00
writeln(info.sampleRate);
write("fileSize: ");
writeln(info.fileSize);
auto bytes = (cast(ubyte*) hfilemap)[0 .. AIMPRemoteAccessMapFileSize];
writeln(bytes);
const wcharsize = wchar.sizeof;
auto pbuff = AIMPRemoteFileInfo.sizeof;
DWORD[TagItem] lengthInfo;
wstring[TagItem] trackInfo;
lengthInfo[TagItem.Album] = info.albumLength;
lengthInfo[TagItem.Artist] = info.artistLength;
lengthInfo[TagItem.Date] = info.dateLength;
lengthInfo[TagItem.FileName] = info.fileNameLength;
lengthInfo[TagItem.Genre] = info.genreLength;
lengthInfo[TagItem.Title] = info.titleLength;
foreach (key; TagItem.min .. TagItem.max) {
auto length = lengthInfo[key];
trackInfo[key] = cast(wstring)(bytes[pbuff .. (pbuff + length * wcharsize)]);
pbuff += length * wcharsize;
}
foreach (key, value; trackInfo) {
writeln(value);
}
}*/